From c3023be794b3025ae4f2256f05cb61ec137b229f Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Mon, 20 Feb 2012 16:31:55 +0530 Subject: [PATCH] notifications of todo items --- css/all-app.css | 14 +- css/all-web.css | 13 ++ .../home/doctype/home_control/home_control.py | 19 +- .../home/page/event_updates/event_updates.js | 24 +- .../home/page/event_updates/event_updates.py | 15 +- erpnext/home/page/my_company/my_company.py | 2 +- erpnext/patches/jan_mar_2012/website/all.py | 4 + erpnext/startup/startup.css | 14 +- erpnext/startup/startup.js | 34 ++- erpnext/startup/toolbar.js | 30 ++- .../utilities/doctype/todo_item/todo_item.txt | 221 ++++++++++++------ js/all-app.js | 34 ++- js/all-web.js | 11 +- version.num | 2 +- 14 files changed, 310 insertions(+), 127 deletions(-) diff --git a/css/all-app.css b/css/all-app.css index 7faff74f9f..5ee09bf888 100644 --- a/css/all-app.css +++ b/css/all-app.css @@ -2252,4 +2252,16 @@ body { .module-icons-selling{ background-position: 0 -528px; } .module-icons-setup{ background-position: 0 -594px; } .module-icons-stock{ background-position: 0 -660px; } -.module-icons-support{ background-position: 0 -726px; } \ No newline at end of file +.module-icons-support{ background-position: 0 -726px; } + +.topbar-new-comments { + margin: -3px 0px; + padding: 2px; + font-size: 14px; + color: #fff; + background-color: #B00D07; + min-width: 20px; + text-align: center; + display: inline-block; + border-radius: 2px; +} diff --git a/css/all-web.css b/css/all-web.css index f576a1a06c..1780c8adf3 100644 --- a/css/all-web.css +++ b/css/all-web.css @@ -1036,6 +1036,19 @@ body { .module-icons-setup{ background-position: 0 -594px; } .module-icons-stock{ background-position: 0 -660px; } .module-icons-support{ background-position: 0 -726px; } + +.topbar-new-comments { + margin: -3px 0px; + padding: 2px; + font-size: 14px; + color: #fff; + background-color: #B00D07; + min-width: 20px; + text-align: center; + display: inline-block; + border-radius: 2px; +} + /* * erpnext/website/css/website.css */#body_div { diff --git a/erpnext/home/doctype/home_control/home_control.py b/erpnext/home/doctype/home_control/home_control.py index 9d821532cd..1999345061 100644 --- a/erpnext/home/doctype/home_control/home_control.py +++ b/erpnext/home/doctype/home_control/home_control.py @@ -197,10 +197,11 @@ class DocType: return count def get_todo_list(self): - return sql("""select name, description, date, + res = sql("""select name, description, `date`, priority, checked, reference_type, reference_name from `tabToDo Item` where owner=%s order by field(priority,'High','Medium','Low') asc, date asc""", \ session['user'], as_dict=1) + return res def add_todo_item(self,args): args = json.loads(args) @@ -213,11 +214,27 @@ class DocType: d.owner = session['user'] d.save(not args.get('name') and 1 or 0) + if args.get('name') and d.checked: + self.notify_assignment(d) + return d.name def remove_todo_item(self,nm): + d = Document('ToDo Item', nm or None) + if d and d.name: + self.notify_assignment(d) sql("delete from `tabToDo Item` where name = %s",nm) + def notify_assignment(self, d): + doc_type = d.fields.get('reference_type') + doc_name = d.fields.get('reference_name') + assigned_by = d.fields.get('assigned_by') + if doc_type and doc_name and assigned_by: + from webnotes.widgets.form import assign_to + assign_to.notify_assignment(assigned_by, d.owner, doc_type, doc_name) + + + # ------------------------------------------------------------------------------------------------------- def dismiss_message(self, arg=''): diff --git a/erpnext/home/page/event_updates/event_updates.js b/erpnext/home/page/event_updates/event_updates.js index 4df78e3541..15f84d9078 100644 --- a/erpnext/home/page/event_updates/event_updates.js +++ b/erpnext/home/page/event_updates/event_updates.js @@ -95,6 +95,7 @@ OnlineUsers = function(wrapper) { if(online_users.length) { var max = online_users.length; max = (max > 10 ? 10 : max) + me.wrapper.innerHTML = ""; for(var i=0; i unread'; - } else { - this.span.innerHTML = 'Team / Messages'; - } - - } -} - pscript.home_make_status = function() { - var home_status_bar = new HomeStatusBar() var wrapper = page_body.pages['Event Updates']; // get values $c_page('home', 'event_updates', 'get_status_details', user, function(r,rt) { - home_status_bar.render(r.message); + page_body.wntoolbar.set_new_comments(r.message.unread_messages); // render online users pscript.online_users_obj.render(r.message.online_users); diff --git a/erpnext/home/page/event_updates/event_updates.py b/erpnext/home/page/event_updates/event_updates.py index 6966b8761c..05f3d93095 100644 --- a/erpnext/home/page/event_updates/event_updates.py +++ b/erpnext/home/page/event_updates/event_updates.py @@ -10,13 +10,16 @@ def get_online_users(arg=None): and t1.user not in ('Guest','Administrator') and TIMESTAMPDIFF(HOUR,t1.lastupdate,NOW()) <= 1""", as_list=1) or [] +@webnotes.whitelist() def get_unread_messages(arg=None): "returns unread (docstatus-0 messages for a user)" - return cint(webnotes.conn.sql("""SELECT COUNT(*) FROM `tabComment Widget Record` - WHERE comment_doctype='My Company' - AND comment_docname = %s - AND ifnull(docstatus,0)=0 - """, webnotes.user.name)[0][0]) + return webnotes.conn.sql("""\ + SELECT name, comment + FROM `tabComment Widget Record` + WHERE comment_doctype='My Company' + AND comment_docname = %s + AND ifnull(docstatus,0)=0 + """, webnotes.user.name, as_list=1) @webnotes.whitelist() def get_status_details(arg=None): @@ -30,8 +33,6 @@ def get_status_details(arg=None): 'user_count': len(online) or 0, 'unread_messages': get_unread_messages(), 'online_users': online or [], - 'is_trial': webnotes.conn.get_global('is_trial'), - 'days_to_expiry': (webnotes.conn.get_global('days_to_expiry') or '0'), 'setup_status': get_setup_status(), 'registration_complete': cint(get_defaults('registration_complete')) and 'Yes' or 'No', 'profile': webnotes.conn.sql("""\ diff --git a/erpnext/home/page/my_company/my_company.py b/erpnext/home/page/my_company/my_company.py index a63e8d9019..ead533344f 100644 --- a/erpnext/home/page/my_company/my_company.py +++ b/erpnext/home/page/my_company/my_company.py @@ -119,7 +119,7 @@ def post_comment(arg): d.comment = arg['comment'] d.save(1) - if cint(arg['notify']): + if cint(arg.get('notify')): fn = webnotes.conn.sql('select first_name, last_name from tabProfile where name=%s', webnotes.user.name)[0] if fn[0] or f[1]: fn = cstr(fn[0]) + (fn[0] and ' ' or '') + cstr(fn[1]) diff --git a/erpnext/patches/jan_mar_2012/website/all.py b/erpnext/patches/jan_mar_2012/website/all.py index 2a55d72e47..c68e65369c 100644 --- a/erpnext/patches/jan_mar_2012/website/all.py +++ b/erpnext/patches/jan_mar_2012/website/all.py @@ -3,6 +3,9 @@ import patches.jan_mar_2012.website.feed import patches.jan_mar_2012.website.website import patches.jan_mar_2012.website.cleanups import patches.jan_mar_2012.website.domain_list +import patches.jan_mar_2012.website.file_data_rename +import patches.jan_mar_2012.website.analytics + def execute(): patches.jan_mar_2012.website.login.execute() @@ -11,3 +14,4 @@ def execute(): patches.jan_mar_2012.website.cleanups.execute() patches.jan_mar_2012.website.domain_list.execute() patches.jan_mar_2012.website.file_data_rename.execute() + patches.jan_mar_2012.website.analytics.execute() diff --git a/erpnext/startup/startup.css b/erpnext/startup/startup.css index 6e368ac483..0fee616035 100644 --- a/erpnext/startup/startup.css +++ b/erpnext/startup/startup.css @@ -43,4 +43,16 @@ body { .module-icons-selling{ background-position: 0 -528px; } .module-icons-setup{ background-position: 0 -594px; } .module-icons-stock{ background-position: 0 -660px; } -.module-icons-support{ background-position: 0 -726px; } \ No newline at end of file +.module-icons-support{ background-position: 0 -726px; } + +.topbar-new-comments { + margin: -3px 0px; + padding: 2px; + font-size: 14px; + color: #fff; + background-color: #B00D07; + min-width: 20px; + text-align: center; + display: inline-block; + border-radius: 2px; +} diff --git a/erpnext/startup/startup.js b/erpnext/startup/startup.js index d40f233b3f..c68650a800 100644 --- a/erpnext/startup/startup.js +++ b/erpnext/startup/startup.js @@ -29,13 +29,16 @@ erpnext.startup.start = function() { // setup toolbar erpnext.toolbar.setup(); + + // set interval for updates + erpnext.startup.set_periodic_updates(); // border to the body // ------------------ $('footer').html(''); } - + $('#startup_div').toggle(false); } @@ -77,6 +80,35 @@ ModulePage = function(parent, module_name, module_label, help_page, callback) { if(callback) this.callback = function(){ callback(); } } +// ========== Update Messages ============ +var update_messages = function() { + // Updates Team Messages + + if(inList(['Guest', 'Administrator'], user)) { return; } + + $c_page('home', 'event_updates', 'get_unread_messages', null, + function(r,rt) { + if(!r.exc) { + // This function is defined in toolbar.js + page_body.wntoolbar.set_new_comments(r.message); + } + } + ); +} + +erpnext.startup.set_periodic_updates = function() { + // Set interval for periodic updates of team messages + wn.updates = {}; + + if(wn.updates.id) { + clearInterval(wn.updates.id); + } + + wn.updates.id = setInterval(update_messages, 180000); +} + +// ======================================= + // start $(document).bind('startup', function() { erpnext.startup.start(); diff --git a/erpnext/startup/toolbar.js b/erpnext/startup/toolbar.js index 49738ce1ee..11499b8d2d 100644 --- a/erpnext/startup/toolbar.js +++ b/erpnext/startup/toolbar.js @@ -3,7 +3,12 @@ wn.provide('erpnext.toolbar'); erpnext.toolbar.setup = function() { // profile - $('#toolbar-user').append('
  • Profile Settings
  • ') + $('#toolbar-user').append('
  • Profile Settings
  • '); + + $('#toolbar-user').append('
  • Team / Messages
  • '); + + $('.topbar .secondary-nav').prepend('\ +
  • '); // help $('.topbar .secondary-nav').append('
  • Billing
  • ') } -} \ No newline at end of file + + $.extend(page_body.wntoolbar, { + set_new_comments: function(new_comments) { + var topbar_nc = $('#toolbar-new-comments'); + if(new_comments && new_comments.length>0) { + topbar_nc.html('' + new_comments.length + ''); + topbar_nc.click(function() { loadpage('My Company'); }); + $.each(new_comments, function(i, v) { + var msg = 'New Message: ' + (v[1].length<=100 ? v[1] : (v[1].substr(0, 100) + "...")); + var id = v[0].replace('/', '-'); + if(!$('#' + id)[0]) { show_alert(msg, id); } + }) + } else { + topbar_nc.html(''); + topbar_nc.click(function() { return false; }); + } + } + }); + + page_body.wntoolbar.set_new_comments(); +} + diff --git a/erpnext/utilities/doctype/todo_item/todo_item.txt b/erpnext/utilities/doctype/todo_item/todo_item.txt index 28745ae3ef..86f5d0da5d 100644 --- a/erpnext/utilities/doctype/todo_item/todo_item.txt +++ b/erpnext/utilities/doctype/todo_item/todo_item.txt @@ -3,140 +3,211 @@ # These values are common in all dictionaries { - 'creation': '2009-05-12 11:19:11', + 'creation': '2009-05-12 16:43:58', 'docstatus': 0, - 'modified': '2010-09-20 14:06:57', - 'modified_by': 'yogesh@webnotestech.com', - 'owner': 'Administrator' + 'modified': '2012-02-17 15:48:54', + 'modified_by': u'Administrator', + 'owner': u'Administrator' }, # These values are common for all DocType { - 'autoname': 'TDI.########', - 'colour': 'White:FFF', + 'allow_attach': 0, + 'allow_copy': 0, + 'allow_email': 0, + 'allow_print': 0, + 'allow_rename': 0, + 'allow_trash': 0, + 'autoname': u'TDI.########', + 'colour': u'White:FFF', 'doctype': 'DocType', + 'hide_heading': 0, + 'hide_toolbar': 0, 'in_create': 1, - 'module': 'Utilities', + 'in_dialog': 0, + 'is_transaction_doc': 0, + 'issingle': 0, + 'max_attachments': 0, + 'module': u'Utilities', 'name': '__common__', 'read_only': 1, - 'section_style': 'Simple', - 'server_code_error': ' ', - 'show_in_menu': 0 + 'read_only_onload': 0, + 'section_style': u'Simple', + 'server_code_error': u' ', + 'show_in_menu': 0, + 'use_template': 0, + 'version': 5 }, # These values are common for all DocField { - 'doctype': 'DocField', + 'doctype': u'DocField', 'name': '__common__', - 'parent': 'ToDo Item', - 'parentfield': 'fields', - 'parenttype': 'DocType', + 'parent': u'ToDo Item', + 'parentfield': u'fields', + 'parenttype': u'DocType', 'permlevel': 0 }, # These values are common for all DocPerm { 'create': 1, - 'doctype': 'DocPerm', - 'idx': 1, + 'doctype': u'DocPerm', 'name': '__common__', - 'parent': 'ToDo Item', - 'parentfield': 'permissions', - 'parenttype': 'DocType', + 'parent': u'ToDo Item', + 'parentfield': u'permissions', + 'parenttype': u'DocType', 'permlevel': 0, 'read': 1, - 'role': 'All' + 'role': u'All', + 'write': 1 }, # DocType, ToDo Item { 'doctype': 'DocType', - 'name': 'ToDo Item' + 'name': u'ToDo Item' }, # DocPerm { - 'doctype': 'DocPerm' + 'doctype': u'DocPerm' }, # DocField { - 'doctype': 'DocField', - 'fieldname': 'description', - 'fieldtype': 'Text', - 'idx': 1, - 'label': 'Description', - 'oldfieldname': 'description', - 'oldfieldtype': 'Text', - 'width': '300px' + 'allow_on_submit': 0, + 'doctype': u'DocField', + 'fieldname': u'description', + 'fieldtype': u'Text', + 'hidden': 0, + 'in_filter': 0, + 'label': u'Description', + 'no_copy': 0, + 'oldfieldname': u'description', + 'oldfieldtype': u'Text', + 'print_hide': 0, + 'report_hide': 0, + 'reqd': 0, + 'search_index': 0, + 'width': u'300px' }, # DocField { - 'doctype': 'DocField', - 'fieldname': 'date', - 'fieldtype': 'Date', - 'idx': 2, - 'label': 'Date', - 'oldfieldname': 'date', - 'oldfieldtype': 'Date', - 'reqd': 1 + 'allow_on_submit': 0, + 'doctype': u'DocField', + 'fieldname': u'date', + 'fieldtype': u'Date', + 'hidden': 0, + 'in_filter': 0, + 'label': u'Date', + 'no_copy': 0, + 'oldfieldname': u'date', + 'oldfieldtype': u'Date', + 'print_hide': 0, + 'report_hide': 0, + 'reqd': 0, + 'search_index': 0 }, # DocField { - 'doctype': 'DocField', - 'fieldname': 'priority', - 'fieldtype': 'Data', - 'idx': 3, - 'label': 'Priority', - 'oldfieldname': 'priority', - 'oldfieldtype': 'Data', - 'reqd': 1 + 'allow_on_submit': 0, + 'doctype': u'DocField', + 'fieldname': u'priority', + 'fieldtype': u'Data', + 'hidden': 0, + 'in_filter': 0, + 'label': u'Priority', + 'no_copy': 0, + 'oldfieldname': u'priority', + 'oldfieldtype': u'Data', + 'print_hide': 0, + 'report_hide': 0, + 'reqd': 0, + 'search_index': 0 }, # DocField { - 'doctype': 'DocField', - 'fieldname': 'reference_type', - 'fieldtype': 'Data', - 'idx': 4, - 'label': 'Reference Type', - 'oldfieldname': 'reference_type', - 'oldfieldtype': 'Data' + 'allow_on_submit': 0, + 'doctype': u'DocField', + 'fieldname': u'reference_type', + 'fieldtype': u'Data', + 'hidden': 0, + 'in_filter': 0, + 'label': u'Reference Type', + 'no_copy': 0, + 'oldfieldname': u'reference_type', + 'oldfieldtype': u'Data', + 'print_hide': 0, + 'report_hide': 0, + 'reqd': 0, + 'search_index': 0 }, # DocField { - 'doctype': 'DocField', - 'fieldname': 'reference_name', - 'fieldtype': 'Data', - 'idx': 5, - 'label': 'Reference Name', - 'oldfieldname': 'reference_name', - 'oldfieldtype': 'Data' + 'allow_on_submit': 0, + 'doctype': u'DocField', + 'fieldname': u'reference_name', + 'fieldtype': u'Data', + 'hidden': 0, + 'in_filter': 0, + 'label': u'Reference Name', + 'no_copy': 0, + 'oldfieldname': u'reference_name', + 'oldfieldtype': u'Data', + 'print_hide': 0, + 'report_hide': 0, + 'reqd': 0, + 'search_index': 0 }, # DocField { - 'doctype': 'DocField', - 'fieldname': 'checked', - 'fieldtype': 'Check', - 'idx': 6, - 'label': 'Checked', - 'oldfieldname': 'checked', - 'oldfieldtype': 'Check' + 'allow_on_submit': 0, + 'doctype': u'DocField', + 'fieldname': u'checked', + 'fieldtype': u'Check', + 'hidden': 0, + 'in_filter': 0, + 'label': u'Checked', + 'no_copy': 0, + 'oldfieldname': u'checked', + 'oldfieldtype': u'Check', + 'print_hide': 0, + 'report_hide': 0, + 'reqd': 0, + 'search_index': 0 }, # DocField { - 'doctype': 'DocField', - 'fieldname': 'role', - 'fieldtype': 'Link', - 'idx': 7, - 'label': 'Role', - 'oldfieldname': 'role', - 'oldfieldtype': 'Link', - 'options': 'Role' + 'allow_on_submit': 0, + 'doctype': u'DocField', + 'fieldname': u'role', + 'fieldtype': u'Link', + 'hidden': 0, + 'in_filter': 0, + 'label': u'Role', + 'no_copy': 0, + 'oldfieldname': u'role', + 'oldfieldtype': u'Link', + 'options': u'Role', + 'print_hide': 0, + 'report_hide': 0, + 'reqd': 0, + 'search_index': 0 + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'assigned_by', + 'fieldtype': u'Link', + 'label': u'Assigned By', + 'options': u'Profile' } ] \ No newline at end of file diff --git a/js/all-app.js b/js/all-app.js index 2b03e1fe18..d0628d23b0 100644 --- a/js/all-app.js +++ b/js/all-app.js @@ -480,8 +480,9 @@ var t=make_table(msg_dialog.rows['Msg'],1,2,'100%',['20px','250px'],{padding:'2p if(!msg_dialog.display)msg_dialog.show();var has_msg=msg_dialog.msg_area.innerHTML?1:0;var m=$a(msg_dialog.msg_area,'div','');if(has_msg)$y(m,{marginTop:'4px'});$dh(msg_dialog.msg_icon);if(msg.substr(0,6).toLowerCase()=='error:'){msg_dialog.msg_icon.src='lib/images/icons/error.gif';$di(msg_dialog.msg_icon);msg=msg.substr(6);}else if(msg.substr(0,8).toLowerCase()=='message:'){msg_dialog.msg_icon.src='lib/images/icons/application.gif';$di(msg_dialog.msg_icon);msg=msg.substr(8);}else if(msg.substr(0,3).toLowerCase()=='ok:'){msg_dialog.msg_icon.src='lib/images/icons/accept.gif';$di(msg_dialog.msg_icon);msg=msg.substr(3);} m.innerHTML=replace_newlines(msg);if(m.offsetHeight>200){$y(m,{height:'200px',width:'400px',overflow:'auto'})} msg_dialog.custom_onhide=callback;} -var growl_area;function show_alert(txt){if(!growl_area){growl_area=$a(popup_cont,'div','',{position:'fixed',bottom:'8px',right:'8px',width:'320px',zIndex:10});} -var wrapper=$a(growl_area,'div','',{position:'relative'});var body=$a(wrapper,'div','notice');var c=$a(body,'div','wn-icon ic-round_delete',{cssFloat:'right'});$(c).click(function(){$dh(this.wrapper)});c.wrapper=wrapper;var t=$a(body,'div','',{color:'#FFF'});$(t).html(txt);$(wrapper).hide().fadeIn(1000);} +var growl_area;function show_alert(txt,id){if(!growl_area){growl_area=$a(popup_cont,'div','',{position:'fixed',bottom:'8px',right:'8px',width:'320px',zIndex:10});} +var wrapper=$a(growl_area,'div','',{position:'relative'});var body=$a(wrapper,'div','notice');var c=$a(body,'div','wn-icon ic-round_delete',{cssFloat:'right'});$(c).click(function(){$dh(this.wrapper)});c.wrapper=wrapper;var t=$a(body,'div','',{color:'#FFF'});$(t).html(txt);if(id){$(t).attr('id',id);} +$(wrapper).hide().fadeIn(1000);} /* * lib/js/legacy/utils/shortcut.js */ @@ -1378,7 +1379,7 @@ if(rd[1]){var dt=rd[0];var dn=rd[1];this.add(dt,dn,0);}}}}); /* * lib/js/wn/ui/toolbar/toolbar.js */ -wn.ui.toolbar.Toolbar=Class.extend({init:function(){this.make();this.make_home();this.make_new();this.make_search();this.make_report();wn.ui.toolbar.recent=new wn.ui.toolbar.RecentDocs();if(in_list(user_roles,'Administrator')) +wn.ui.toolbar.Toolbar=Class.extend({init:function(){this.make();this.make_home();this.make_document();wn.ui.toolbar.recent=new wn.ui.toolbar.RecentDocs();if(in_list(user_roles,'Administrator')) this.make_options();this.make_tools();this.set_user_name();this.make_logout();$('.topbar').dropdown();$(document).trigger('toolbar_setup');},make:function(){$('header').append('
    \
    \
    \ @@ -1395,10 +1396,14 @@ this.make_options();this.make_tools();this.set_user_name();this.make_logout();$( \
    \
    \ -
    ');},make_home:function(){$('.topbar .nav:first').append('
  • Home
  • ')},make_new:function(){wn.ui.toolbar.new_dialog=new wn.ui.toolbar.NewDialog();$('.topbar .nav:first').append('
  • New
  • ');},make_search:function(){wn.ui.toolbar.search=new wn.ui.toolbar.Search();$('.topbar .nav:first').append('
  • Search
  • ');},make_report:function(){wn.ui.toolbar.report=new wn.ui.toolbar.Report();$('.topbar .nav:first').append('
  • Report
  • ');},make_tools:function(){$('.topbar .nav:first').append('
  • Home
  • ')},make_document:function(){wn.ui.toolbar.new_dialog=new wn.ui.toolbar.NewDialog();wn.ui.toolbar.search=new wn.ui.toolbar.Search();wn.ui.toolbar.report=new wn.ui.toolbar.Report();$('.topbar .nav:first').append('');},make_tools:function(){$('.topbar .nav:first').append('