Skip to content

Commit

Permalink
feat: post metrics and some fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
anupamvs committed Apr 14, 2021
1 parent 16bf1e8 commit 8fef290
Show file tree
Hide file tree
Showing 7 changed files with 215 additions and 124 deletions.
65 changes: 42 additions & 23 deletions erpnext/crm/doctype/linkedin_settings/linkedin_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
# For license information, please see license.txt

from __future__ import unicode_literals
import frappe, requests, json
import frappe, requests
from frappe import _
from frappe.utils import get_site_url, get_url_to_form, get_link_to_form
from frappe.utils import get_site_url, get_url_to_form
from frappe.model.document import Document
from frappe.utils.file_manager import get_file, get_file_path
from frappe.utils.file_manager import get_file_path
from six.moves.urllib.parse import urlencode

class LinkedInSettings(Document):
Expand Down Expand Up @@ -51,16 +51,16 @@ def get_member_profile(self):
"session_status": "Active"
})
frappe.local.response["type"] = "redirect"
frappe.local.response["location"] = get_url_to_form("LinkedIn Settings","LinkedIn Settings")
frappe.local.response["location"] = get_url_to_form("LinkedIn Settings", "LinkedIn Settings")

def post(self, text, media=None):
def post(self, text, title, media=None):
if not media:
return self.post_text(text)
return self.post_text(text, title)
else:
media_id = self.upload_image(media)

if media_id:
return self.post_text(text, media_id=media_id)
return self.post_text(text, title, media_id=media_id)
else:
frappe.log_error("Failed to upload media.","LinkedIn Upload Error")

Expand Down Expand Up @@ -94,7 +94,7 @@ def upload_image(self, media):

return None

def post_text(self, text, media_id=None):
def post_text(self, text, title, media_id=None):
url = "https://api.linkedin.com/v2/shares"
headers = self.get_headers()
headers["X-Restli-Protocol-Version"] = "2.0.0"
Expand All @@ -105,7 +105,7 @@ def post_text(self, text, media_id=None):
"linkedInDistributionTarget": {}
},
"owner":"urn:li:organization:{0}".format(self.company_id),
"subject": "Test Share Subject",
"subject": title,
"text": {
"text": text
}
Expand Down Expand Up @@ -144,18 +144,8 @@ def http_post(self, url, headers=None, body=None, data=None):
raise

except Exception as e:
content = json.loads(response.content)

if response.status_code == 401:
self.db_set("session_status", "Expired")
frappe.db.commit()
frappe.throw(content["message"], title="LinkedIn Error - Unauthorized")
elif response.status_code == 403:
frappe.msgprint(_("You Didn't have permission to access this API"))
frappe.throw(content["message"], title="LinkedIn Error - Access Denied")
else:
frappe.throw(response.reason, title=response.status_code)

self.api_error(response)

return response

def get_headers(self):
Expand All @@ -172,11 +162,40 @@ def get_reference_url(self, text):

def delete_post(self, post_id):
try:
response = requests.delete("https://api.linkedin.com/v2/shares/{0}".format(post_id), self.get_headers())
response = requests.delete(url="https://api.linkedin.com/v2/shares/urn:li:share:{0}".format(post_id), headers=self.get_headers())
if response.status_code !=200:
raise
except Exception as e:
self.api_error(response)

def get_post(self, post_id):
url = "https://api.linkedin.com/v2/organizationalEntityShareStatistics?q=organizationalEntity&organizationalEntity=urn:li:organization:{0}&shares[0]=urn:li:share:{1}".format(self.company_id, post_id)

try:
response = requests.get(url=url, headers=self.get_headers())
if response.status_code !=200:
raise

except Exception as e:
content = json.loads(response.content)
self.api_error(response)

response = frappe.parse_json(response.content.decode())
if len(response.elements):
return response.elements[0]

return None

def api_error(self, response):
content = frappe.parse_json(response.content.decode())

if response.status_code == 401:
self.db_set("session_status", "Expired")
frappe.db.commit()
frappe.throw(content["message"], title="LinkedIn Error - Unauthorized")
elif response.status_code == 403:
frappe.msgprint(_("You Didn't have permission to access this API"))
frappe.throw(content["message"], title="LinkedIn Error - Access Denied")
else:
frappe.throw(response.reason, title=response.status_code)

@frappe.whitelist(allow_guest=True)
Expand Down

This file was deleted.

165 changes: 115 additions & 50 deletions erpnext/crm/doctype/social_media_post/social_media_post.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,66 +9,131 @@ frappe.ui.form.on('Social Media Post', {
let scheduled_time = new Date(frm.doc.scheduled_time);
let date_time = new Date();
if (scheduled_time.getTime() < date_time.getTime()){
frappe.throw(__("Invalid Scheduled Time"));
frappe.throw(__("Scheduled Time must be a future time."));
}
}
if (frm.doc.text?.length > 280){
frappe.throw(__("Length Must be less than 280."))
frm.trigger('validate_tweet_length');
},

text: function(frm) {
frm.set_df_property('text', 'description', `${frm.doc.text.length}/280`);
frm.refresh_field('text');
frm.trigger('validate_tweet_length');
},

validate_tweet_length: function(frm) {
if (frm.doc?.text?.length > 280){
frappe.throw(__("Tweet length Must be less than 280."))
}
},

onload: function(frm) {
frm.trigger('make_dashboard');
},

make_dashboard: function(frm) {
if (frm.doc.post_status == "Posted") {
frappe.call({
doc: frm.doc,
method: 'get_post',
freeze: true,
callback: (r) => {
if (!r.message) {
return
}

let datasets = [],colors = []
if (r.message?.twitter) {
window.post = r.message
colors.push('#1DA1F2')
datasets.push({
name: 'Twitter',
values: [r.message.twitter.favorite_count, r.message.twitter.retweet_count]
})
}
if (r.message?.linkedin) {
colors.push('#0077b5')
datasets.push({
name: 'LinkedIn',
values: [r.message.linkedin.totalShareStatistics.likeCount, r.message.linkedin.totalShareStatistics.shareCount]
})
}

if(datasets.length) {
frm.dashboard.render_graph({
data: {
labels: ['Likes', 'Retweets/Shares'],
datasets: datasets
},

title: "Post Metrics",
type: 'bar',
height: 300,
colors: colors
});
}
}
});
}
},

refresh: function(frm){
frm.trigger('text');

if (frm.doc.docstatus === 1){
if (frm.doc.post_status != "Posted"){
add_post_btn(frm);
if (!['Posted', 'Deleted'].includes(frm.doc.post_status)){
frm.trigger('add_post_btn');
}
else {
frappe.call({
doc: frm.doc,
method: 'get_status',
callback: function() {

}
if(frm.doc.post_status !='Deleted') {
frm.add_custom_button(('Delete Post'), function(){
frappe.confirm(
__('Are you sure want to delete the Post from Social Media platforms?'),
function(){
frappe.call({
doc: frm.doc,
method: 'delete_post',
freeze: true,
callback: (r) => {
frm.reload_doc();
}
});
}
)
});
frm.disable_form();
}

let html='';
if (frm.doc.twitter){
let color = frm.doc.twitter_post_id ? "green" : "red";
let status = frm.doc.twitter_post_id ? "Posted" : "Not Posted";
html += `<div class="col-xs-6">
<span class="indicator whitespace-nowrap ${color}"><span>Twitter : ${status} </span></span>
</div>` ;
}
if (frm.doc.linkedin){
let color = frm.doc.linkedin_post_id ? "green" : "red";
let status = frm.doc.linkedin_post_id ? "Posted" : "Not Posted";
html += `<div class="col-xs-6">
<span class="indicator whitespace-nowrap ${color}"><span>LinkedIn : ${status} </span></span>
</div>` ;
if (frm.doc.post_status !='Deleted') {
let html='';
if (frm.doc.twitter){
let color = frm.doc.twitter_post_id ? "green" : "red";
let status = frm.doc.twitter_post_id ? "Posted" : "Not Posted";
html += `<div class="col-xs-6">
<span class="indicator whitespace-nowrap ${color}"><span>Twitter : ${status} </span></span>
</div>` ;
}
if (frm.doc.linkedin){
let color = frm.doc.linkedin_post_id ? "green" : "red";
let status = frm.doc.linkedin_post_id ? "Posted" : "Not Posted";
html += `<div class="col-xs-6">
<span class="indicator whitespace-nowrap ${color}"><span>LinkedIn : ${status} </span></span>
</div>` ;
}
html = `<div class="row">${html}</div>`;
frm.dashboard.set_headline_alert(html);
}
html = `<div class="row">${html}</div>`;
frm.dashboard.set_headline_alert(html);
}
},

add_post_btn: function(frm) {
frm.add_custom_button(__('Post Now'), function(){
frappe.call({
doc: frm.doc,
method: 'post',
freeze: true,
callback: function(r) {
frm.reload_doc();
}
});
});
}
});
var add_post_btn = function(frm){
frm.add_custom_button(('Post Now'), function(){
post(frm);
});
}
var post = function(frm){
frappe.dom.freeze();
frappe.call({
method: "erpnext.crm.doctype.social_media_post.social_media_post.publish",
args: {
doctype: frm.doc.doctype,
name: frm.doc.name
},
callback: function(r) {
frm.reload_doc();
frappe.dom.unfreeze();
}
})

}
});
4 changes: 2 additions & 2 deletions erpnext/crm/doctype/social_media_post/social_media_post.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@
"fieldtype": "Select",
"label": "Post Status",
"no_copy": 1,
"options": "\nScheduled\nPosted\nCancelled\nError",
"options": "\nScheduled\nPosted\nCancelled\nDeleted\nError",
"read_only": 1
},
{
Expand Down Expand Up @@ -152,7 +152,7 @@
],
"is_submittable": 1,
"links": [],
"modified": "2021-02-18 14:06:44.633463",
"modified": "2021-04-14 14:24:59.821223",
"modified_by": "Administrator",
"module": "CRM",
"name": "Social Media Post",
Expand Down
Loading

0 comments on commit 8fef290

Please sign in to comment.