@@ -9,6 +9,7 @@ bootstrap client session | |||||
import frappe | import frappe | ||||
import frappe.defaults | import frappe.defaults | ||||
import frappe.widgets.page | import frappe.widgets.page | ||||
from frappe.utils import get_gravatar | |||||
def get_bootinfo(): | def get_bootinfo(): | ||||
"""build and return boot info""" | """build and return boot info""" | ||||
@@ -92,18 +93,14 @@ def get_fullnames(): | |||||
"""map of user fullnames""" | """map of user fullnames""" | ||||
ret = frappe.db.sql("""select name, | ret = frappe.db.sql("""select name, | ||||
concat(ifnull(first_name, ''), | concat(ifnull(first_name, ''), | ||||
if(ifnull(last_name, '')!='', ' ', ''), ifnull(last_name, '')), | |||||
user_image, gender, email | |||||
from tabUser where ifnull(enabled, 0)=1""", as_list=1) | |||||
if(ifnull(last_name, '')!='', ' ', ''), ifnull(last_name, '')) as fullname, | |||||
user_image as image, gender, email | |||||
from tabUser where ifnull(enabled, 0)=1""", as_dict=1) | |||||
d = {} | d = {} | ||||
for r in ret: | for r in ret: | ||||
if not r[2]: | |||||
r[2] = '/assets/frappe/images/ui/avatar.png' | |||||
else: | |||||
r[2] = r[2] | |||||
d[r[0]]= {'fullname': r[1], 'image': r[2], 'gender': r[3], | |||||
'email': r[4] or r[0]} | |||||
if not r.image: | |||||
r.image = get_gravatar() | |||||
d[r.name] = r | |||||
return d | return d | ||||
@@ -3,7 +3,7 @@ | |||||
"allow_copy": 0, | "allow_copy": 0, | ||||
"allow_import": 1, | "allow_import": 1, | ||||
"allow_rename": 1, | "allow_rename": 1, | ||||
"creation": "2014-03-11 14:55:00.000000", | |||||
"creation": "2014-03-11 14:55:00", | |||||
"description": "Represents a User in the system.", | "description": "Represents a User in the system.", | ||||
"docstatus": 0, | "docstatus": 0, | ||||
"doctype": "DocType", | "doctype": "DocType", | ||||
@@ -116,6 +116,7 @@ | |||||
"permlevel": 0 | "permlevel": 0 | ||||
}, | }, | ||||
{ | { | ||||
"description": "Get your globally recognized avatar from <a href=\"https://gravatar.com/\">Gravatar.com</a>", | |||||
"fieldname": "user_image", | "fieldname": "user_image", | ||||
"fieldtype": "Attach", | "fieldtype": "Attach", | ||||
"hidden": 0, | "hidden": 0, | ||||
@@ -420,7 +421,7 @@ | |||||
"issingle": 0, | "issingle": 0, | ||||
"istable": 0, | "istable": 0, | ||||
"max_attachments": 5, | "max_attachments": 5, | ||||
"modified": "2014-03-11 16:04:13.000000", | |||||
"modified": "2014-05-30 02:05:20.655024", | |||||
"modified_by": "Administrator", | "modified_by": "Administrator", | ||||
"module": "Core", | "module": "Core", | ||||
"name": "User", | "name": "User", | ||||
@@ -3,7 +3,7 @@ | |||||
from __future__ import unicode_literals | from __future__ import unicode_literals | ||||
import frappe | import frappe | ||||
from frappe.utils import cint, now | |||||
from frappe.utils import cint, now, get_gravatar | |||||
from frappe import throw, msgprint, _ | from frappe import throw, msgprint, _ | ||||
from frappe.auth import _update_password | from frappe.auth import _update_password | ||||
import frappe.permissions | import frappe.permissions | ||||
@@ -90,10 +90,8 @@ class User(Document): | |||||
pass # email server not set, don't send email | pass # email server not set, don't send email | ||||
def update_gravatar(self): | def update_gravatar(self): | ||||
import md5 | |||||
if not self.user_image: | if not self.user_image: | ||||
self.user_image = "https://secure.gravatar.com/avatar/" + md5.md5(self.name).hexdigest() \ | |||||
+ "?d=retro" | |||||
self.user_image = get_gravatar(self.name) | |||||
@Document.hook | @Document.hook | ||||
def validate_reset_password(self): | def validate_reset_password(self): | ||||
@@ -1,5 +1,5 @@ | |||||
// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors | // Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors | ||||
// MIT License. See license.txt | |||||
// MIT License. See license.txt | |||||
frappe.provide('frappe.core.pages.messages'); | frappe.provide('frappe.core.pages.messages'); | ||||
@@ -8,9 +8,8 @@ frappe.pages.messages.onload = function(wrapper) { | |||||
parent: wrapper, | parent: wrapper, | ||||
title: "Messages" | title: "Messages" | ||||
}); | }); | ||||
$('<div><div class="avatar avatar-large">\ | |||||
<img id="avatar-image" src="assets/frappe/images/ui/avatar.png"></div>\ | |||||
$('<div><h3><i class="icon-group"></i></h3></div>\ | |||||
<h3 style="display: inline-block" id="message-title">Everyone</h3>\ | <h3 style="display: inline-block" id="message-title">Everyone</h3>\ | ||||
</div><hr>\ | </div><hr>\ | ||||
<div id="post-message">\ | <div id="post-message">\ | ||||
@@ -20,14 +19,14 @@ frappe.pages.messages.onload = function(wrapper) { | |||||
<div class="all-messages"></div><br>').appendTo($(wrapper).find('.layout-main-section')); | <div class="all-messages"></div><br>').appendTo($(wrapper).find('.layout-main-section')); | ||||
wrapper.appframe.add_module_icon("Messages"); | wrapper.appframe.add_module_icon("Messages"); | ||||
frappe.core.pages.messages = new frappe.core.pages.messages(wrapper); | frappe.core.pages.messages = new frappe.core.pages.messages(wrapper); | ||||
} | } | ||||
$(frappe.pages.messages).bind('show', function() { | $(frappe.pages.messages).bind('show', function() { | ||||
// remove alerts | // remove alerts | ||||
$('#alert-container .alert').remove(); | $('#alert-container .alert').remove(); | ||||
frappe.core.pages.messages.show(); | frappe.core.pages.messages.show(); | ||||
setTimeout("frappe.core.pages.messages.refresh()", 5000); | setTimeout("frappe.core.pages.messages.refresh()", 5000); | ||||
}) | }) | ||||
@@ -38,11 +37,11 @@ frappe.core.pages.messages = Class.extend({ | |||||
this.show_active_users(); | this.show_active_users(); | ||||
this.make_post_message(); | this.make_post_message(); | ||||
this.make_list(); | this.make_list(); | ||||
//this.update_messages('reset'); //Resets notification icons | |||||
//this.update_messages('reset'); //Resets notification icons | |||||
}, | }, | ||||
make_post_message: function() { | make_post_message: function() { | ||||
var me = this; | var me = this; | ||||
$('#post-message .btn').click(function() { | $('#post-message .btn').click(function() { | ||||
var txt = $('#post-message textarea').val(); | var txt = $('#post-message textarea').val(); | ||||
if(txt) { | if(txt) { | ||||
@@ -60,7 +59,7 @@ frappe.core.pages.messages = Class.extend({ | |||||
}, | }, | ||||
btn: this | btn: this | ||||
}); | }); | ||||
} | |||||
} | |||||
}); | }); | ||||
}, | }, | ||||
show: function() { | show: function() { | ||||
@@ -72,20 +71,20 @@ frappe.core.pages.messages = Class.extend({ | |||||
$('#avatar-image').attr("src", frappe.utils.get_file_link(frappe.user_info(contact).image)); | $('#avatar-image').attr("src", frappe.utils.get_file_link(frappe.user_info(contact).image)); | ||||
$("#show-everyone").toggle(contact!==user); | $("#show-everyone").toggle(contact!==user); | ||||
$("#post-message button").text(contact==user ? __("Post Publicly") : __("Post to user")) | $("#post-message button").text(contact==user ? __("Post Publicly") : __("Post to user")) | ||||
this.contact = contact; | this.contact = contact; | ||||
this.list.opts.args.contact = contact; | this.list.opts.args.contact = contact; | ||||
this.list.run(); | this.list.run(); | ||||
}, | }, | ||||
// check for updates every 5 seconds if page is active | // check for updates every 5 seconds if page is active | ||||
refresh: function() { | refresh: function() { | ||||
setTimeout("frappe.core.pages.messages.refresh()", 5000); | setTimeout("frappe.core.pages.messages.refresh()", 5000); | ||||
if(frappe.container.page.label != 'Messages') | |||||
if(frappe.container.page.label != 'Messages') | |||||
return; | return; | ||||
if(!frappe.session_alive) | |||||
if(!frappe.session_alive) | |||||
return; | return; | ||||
this.show(); | this.show(); | ||||
}, | }, | ||||
@@ -110,7 +109,7 @@ frappe.core.pages.messages = Class.extend({ | |||||
no_loading: true, | no_loading: true, | ||||
render_row: function(wrapper, data) { | render_row: function(wrapper, data) { | ||||
$(wrapper).removeClass('list-row'); | $(wrapper).removeClass('list-row'); | ||||
data.creation = dateutil.comment_when(data.creation); | data.creation = dateutil.comment_when(data.creation); | ||||
data.comment_by_fullname = frappe.user_info(data.owner).fullname; | data.comment_by_fullname = frappe.user_info(data.owner).fullname; | ||||
data.image = frappe.utils.get_file_link(frappe.user_info(data.owner).image); | data.image = frappe.utils.get_file_link(frappe.user_info(data.owner).image); | ||||
@@ -119,7 +118,7 @@ frappe.core.pages.messages = Class.extend({ | |||||
data.reply_html = ''; | data.reply_html = ''; | ||||
if(data.owner==user) { | if(data.owner==user) { | ||||
data.cls = 'message-self'; | data.cls = 'message-self'; | ||||
data.comment_by_fullname = 'You'; | |||||
data.comment_by_fullname = 'You'; | |||||
} else { | } else { | ||||
data.cls = 'message-other'; | data.cls = 'message-other'; | ||||
} | } | ||||
@@ -131,7 +130,7 @@ frappe.core.pages.messages = Class.extend({ | |||||
onclick="frappe.core.pages.messages.delete(this)"\ | onclick="frappe.core.pages.messages.delete(this)"\ | ||||
data-name="%(name)s">×</a>', data); | data-name="%(name)s">×</a>', data); | ||||
} | } | ||||
if(data.owner==data.comment_docname && data.parenttype!="Assignment") { | if(data.owner==data.comment_docname && data.parenttype!="Assignment") { | ||||
data.mark_html = "<div class='message-mark' title='Public'\ | data.mark_html = "<div class='message-mark' title='Public'\ | ||||
style='background-color: green'></div>" | style='background-color: green'></div>" | ||||
@@ -171,7 +170,7 @@ frappe.core.pages.messages = Class.extend({ | |||||
').appendTo($body); | ').appendTo($body); | ||||
$("#show-everyone").toggle(me.contact!==user); | $("#show-everyone").toggle(me.contact!==user); | ||||
r.message.sort(function(a, b) { return b.has_session - a.has_session; }); | r.message.sort(function(a, b) { return b.has_session - a.has_session; }); | ||||
for(var i in r.message) { | for(var i in r.message) { | ||||
var p = r.message[i]; | var p = r.message[i]; | ||||
@@ -186,7 +185,7 @@ frappe.core.pages.messages = Class.extend({ | |||||
title="%(status)s"><img src="%(image)s" /></span>\ | title="%(status)s"><img src="%(image)s" /></span>\ | ||||
<a href="#!messages/%(name)s">%(fullname)s</a>\ | <a href="#!messages/%(name)s">%(fullname)s</a>\ | ||||
</p>', p)) | </p>', p)) | ||||
.appendTo($body); | |||||
.appendTo($body); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -4,17 +4,11 @@ | |||||
// misc user functions | // misc user functions | ||||
frappe.user_info = function(uid) { | frappe.user_info = function(uid) { | ||||
var def = { | |||||
'fullname':uid, | |||||
'image': 'assets/frappe/images/ui/avatar.png' | |||||
} | |||||
if(!frappe.boot.user_info) return def | |||||
if(!frappe.boot.user_info[uid]) return def | |||||
if(!frappe.boot.user_info[uid].fullname) | |||||
frappe.boot.user_info[uid].fullname = uid; | |||||
if(!frappe.boot.user_info[uid].image) | |||||
frappe.boot.user_info[uid].image = def.image; | |||||
return frappe.boot.user_info[uid]; | |||||
if(!uid) | |||||
uid = user; | |||||
if(!frappe.boot.user_info) | |||||
return {fullname:"Unknown"}; | |||||
return frappe.boot.user_info[uid] || {}; | |||||
} | } | ||||
frappe.avatar = function(user, large, title) { | frappe.avatar = function(user, large, title) { | ||||
@@ -54,6 +54,9 @@ frappe.search = { | |||||
response(frappe.search.options); | response(frappe.search.options); | ||||
}, | }, | ||||
focus: function(event, ui) { | |||||
return false; | |||||
}, | |||||
select: function(event, ui) { | select: function(event, ui) { | ||||
if(ui.item.route_options) { | if(ui.item.route_options) { | ||||
frappe.route_options = ui.item.route_options; | frappe.route_options = ui.item.route_options; | ||||
@@ -67,7 +70,7 @@ frappe.search = { | |||||
setTimeout(function() { $("#navbar-search").val(""); }, 100); | setTimeout(function() { $("#navbar-search").val(""); }, 100); | ||||
} | } | ||||
}).data('ui-autocomplete')._renderItem = function(ul, d) { | }).data('ui-autocomplete')._renderItem = function(ul, d) { | ||||
var html = "<strong class='small'>" + d.value + "</strong>"; | |||||
var html = "<span class='small'>" + d.value + "</span>"; | |||||
if(d.description && d.value!==d.description) { | if(d.description && d.value!==d.description) { | ||||
html += '<br><span class="small text-muted">' + d.description + '</span>'; | html += '<br><span class="small text-muted">' + d.description + '</span>'; | ||||
} | } | ||||
@@ -97,7 +100,7 @@ frappe.search.verbs = [ | |||||
var route = frappe.get_route(); | var route = frappe.get_route(); | ||||
if(route[0]==="List") { | if(route[0]==="List") { | ||||
frappe.search.options.push({ | frappe.search.options.push({ | ||||
value: __('Find "{0}" in {1}', [txt, route[1]]), | |||||
value: __('Find {0} in {1}', ["<b>"+txt+"</b>", "<b>" + route[1] + "</b>"]), | |||||
route_options: {"name": ["like", "%" + txt + "%"]}, | route_options: {"name": ["like", "%" + txt + "%"]}, | ||||
onclick: function() { | onclick: function() { | ||||
frappe.container.page.doclistview.set_route_options(); | frappe.container.page.doclistview.set_route_options(); | ||||
@@ -113,7 +116,7 @@ frappe.search.verbs = [ | |||||
if(txt.split(" ")[0]==="new") { | if(txt.split(" ")[0]==="new") { | ||||
frappe.search.find(frappe.boot.user.can_create, txt.substr(4), function(match) { | frappe.search.find(frappe.boot.user.can_create, txt.substr(4), function(match) { | ||||
return { | return { | ||||
value:__("New {0}", [match]), | |||||
value:__("New {0}", ["<b>"+match+"</b>"]), | |||||
route:["Form", match, "New " + match] | route:["Form", match, "New " + match] | ||||
} | } | ||||
}); | }); | ||||
@@ -124,7 +127,7 @@ frappe.search.verbs = [ | |||||
function(txt) { | function(txt) { | ||||
frappe.search.find(frappe.boot.user.can_read, txt, function(match) { | frappe.search.find(frappe.boot.user.can_read, txt, function(match) { | ||||
return { | return { | ||||
value: __("{0} List", [match]), | |||||
value: __("{0} List", ["<b>"+match+"</b>"]), | |||||
route:["List", match] | route:["List", match] | ||||
} | } | ||||
}); | }); | ||||
@@ -134,7 +137,7 @@ frappe.search.verbs = [ | |||||
function(txt) { | function(txt) { | ||||
frappe.search.find(keys(frappe.boot.page_info), txt, function(match) { | frappe.search.find(keys(frappe.boot.page_info), txt, function(match) { | ||||
return { | return { | ||||
value: __("Open {0}", [match]), | |||||
value: __("Open {0}", ["<b>"+match+"</b>"]), | |||||
route: [match] | route: [match] | ||||
} | } | ||||
}); | }); | ||||
@@ -144,12 +147,12 @@ frappe.search.verbs = [ | |||||
function(txt) { | function(txt) { | ||||
frappe.search.find(keys(frappe.modules), txt, function(match) { | frappe.search.find(keys(frappe.modules), txt, function(match) { | ||||
ret = { | ret = { | ||||
value: __("Open {0}", [match]), | |||||
value: __("Open {0}", ["<b>"+match+"</b>"]), | |||||
} | } | ||||
if(frappe.modules[match].link) { | if(frappe.modules[match].link) { | ||||
ret.route = [frappe.modules[match].link]; | ret.route = [frappe.modules[match].link]; | ||||
} else { | } else { | ||||
ret.route = ["Module", match]; | |||||
ret.route = ["Module", "<b>"+match+"</b>"]; | |||||
} | } | ||||
return ret; | return ret; | ||||
}); | }); | ||||
@@ -161,7 +164,7 @@ frappe.search.verbs = [ | |||||
parts = txt.split(" in "); | parts = txt.split(" in "); | ||||
frappe.search.find(frappe.boot.user.can_read, parts[1], function(match) { | frappe.search.find(frappe.boot.user.can_read, parts[1], function(match) { | ||||
return { | return { | ||||
value: __('Find "{0}" in {1}', [parts[0], match]), | |||||
value: __('Find {0} in {1}', ["<b>"+parts[0]+"</b>", "<b>"+match+"</b>"]), | |||||
route_options: {"name": ["like", "%" + parts[0] + "%"]}, | route_options: {"name": ["like", "%" + parts[0] + "%"]}, | ||||
route: ["List", match] | route: ["List", match] | ||||
} | } | ||||
@@ -179,17 +182,17 @@ frappe.search.verbs = [ | |||||
try { | try { | ||||
var val = eval(txt); | var val = eval(txt); | ||||
frappe.search.options.push({ | |||||
value: $.format('{0} = {1}', [txt, "<b>"+val+"</b>"]), | |||||
match: val, | |||||
onclick: function(match) { | |||||
msgprint(match, "Result"); | |||||
} | |||||
}); | |||||
} catch(e) { | } catch(e) { | ||||
var val = e.message; | |||||
// pass | |||||
} | } | ||||
frappe.search.options.push({ | |||||
value: $.format('"{0}" = {1}', [txt, val]), | |||||
match: val, | |||||
onclick: function(match) { | |||||
msgprint(match, "Result"); | |||||
} | |||||
}); | |||||
}; | }; | ||||
}, | }, | ||||
]; | ]; |
@@ -131,9 +131,8 @@ frappe.ui.toolbar.Toolbar = Class.extend({ | |||||
</li>'); | </li>'); | ||||
}, | }, | ||||
set_user_name: function() { | set_user_name: function() { | ||||
var fn = user_fullname; | |||||
if(fn.length > 15) fn = fn.substr(0,12) + '...'; | |||||
$('#toolbar-user-name').html(fn); | |||||
$('#toolbar-user-name').html('<img src="' | |||||
+frappe.user_info().image+'" style="max-width: 24px; max-height: 24px">'); | |||||
}, | }, | ||||
make_user_menu: function() { | make_user_menu: function() { | ||||
@@ -75,6 +75,10 @@ def random_string(length): | |||||
from random import choice | from random import choice | ||||
return ''.join([choice(string.letters + string.digits) for i in range(length)]) | return ''.join([choice(string.letters + string.digits) for i in range(length)]) | ||||
def get_gravatar(email): | |||||
import md5 | |||||
return "https://secure.gravatar.com/avatar/" + md5.md5(email).hexdigest() | |||||
def get_traceback(): | def get_traceback(): | ||||
""" | """ | ||||
Returns the traceback of the Exception | Returns the traceback of the Exception | ||||