diff --git a/config.json b/config.json new file mode 100644 index 0000000000..ffc6d2cc13 --- /dev/null +++ b/config.json @@ -0,0 +1,32 @@ +{ + "modules": { + "Activity": { + "type": "page", + "link": "activity", + "color": "#633501", + "icon": "icon-play", + "label": "Activity" + }, + "To Do": { + "type": "page", + "link": "todo", + "color": "#febf04", + "label": "To Do", + "icon": "icon-check" + }, + "Calendar": { + "type": "view", + "link": "Calendar/Event", + "color": "#026584", + "label": "Calendar", + "icon": "icon-calendar" + }, + "Messages": { + "type": "page", + "link": "messages", + "color": "#8d016e", + "label": "Messages", + "icon": "icon-comments" + } + } +} \ No newline at end of file diff --git a/core/page/desktop/desktop.js b/core/page/desktop/desktop.js index 87181d8a98..9b1e9e1610 100644 --- a/core/page/desktop/desktop.js +++ b/core/page/desktop/desktop.js @@ -42,7 +42,7 @@ erpnext.desktop.render = function() { // modules var modules_list = wn.user.get_desktop_items(); $.each(modules_list, function(i, m) { - if(!in_list(['Setup', 'Core'], m) && wn.boot.profile.allow_modules.indexOf(m)!=-1) + if(m!="Setup") add_icon(m); }) diff --git a/core/page/messages/__init__.py b/core/page/messages/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/core/page/messages/messages.css b/core/page/messages/messages.css new file mode 100644 index 0000000000..88bbde7e86 --- /dev/null +++ b/core/page/messages/messages.css @@ -0,0 +1,32 @@ +#message-post-text { +} + +#message-list { +} + +.message { + padding: 7px; + padding-left: 17px; + border-bottom: 1px solid #ccc; +} + +.message-mark { + margin-left: -17px; + width: 9px; + position: absolute; + height: 30px; +} + +.message .help { + margin-bottom: 0px; + padding-bottom: 0px; + color: #888; + font-size: 11px; +} + +.message-other { +} + +.message-self { + background-color: #eee; +} \ No newline at end of file diff --git a/core/page/messages/messages.html b/core/page/messages/messages.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/core/page/messages/messages.js b/core/page/messages/messages.js new file mode 100644 index 0000000000..cf5d790e53 --- /dev/null +++ b/core/page/messages/messages.js @@ -0,0 +1,214 @@ +// ERPNext - web based ERP (http://erpnext.com) +// Copyright (C) 2012 Web Notes Technologies Pvt Ltd +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU 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 General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +wn.provide('erpnext.messages'); + +wn.pages.messages.onload = function(wrapper) { + wn.ui.make_app_page({ + parent: wrapper, + title: "Messages" + }); + + $('
\ +
\ +

Everyone

\ +

\ +
\ + \ +

\ +
\ +
').appendTo($(wrapper).find('.layout-main-section')); + + wrapper.appframe.add_home_breadcrumb(); + wrapper.appframe.add_breadcrumb(wn.modules["Messages"].icon); + + erpnext.messages = new erpnext.Messages(wrapper); + erpnext.toolbar.set_new_comments(0); +} + +$(wn.pages.messages).bind('show', function() { + // remove alerts + $('#alert-container .alert').remove(); + + erpnext.toolbar.set_new_comments(0); + erpnext.messages.show(); + setTimeout("erpnext.messages.refresh()", 17000); +}) + +erpnext.Messages = Class.extend({ + init: function(wrapper) { + this.wrapper = wrapper; + this.show_active_users(); + this.make_post_message(); + this.make_list(); + //this.update_messages('reset'); //Resets notification icons + }, + make_post_message: function() { + var me = this; + $('#post-message textarea').keydown(function(e) { + if(e.which==13) { + $('#post-message .btn').click(); + return false; + } + }); + + $('#post-message .btn').click(function() { + var txt = $('#post-message textarea').val(); + if(txt) { + wn.call({ + module:'core', + page:'messages', + method:'post', + args: { + txt: txt, + contact: me.contact + }, + callback:function(r,rt) { + $('#post-message textarea').val('') + me.list.run(); + }, + btn: this + }); + } + }); + }, + show: function() { + var contact = this.get_contact() || this.contact || user; + + $('#message-title').html(contact==user ? "Everyone" : + wn.user_info(contact).fullname) + + $('#avatar-image').attr("src", wn.utils.get_file_link(wn.user_info(contact).image)); + + $("#show-everyone").toggle(contact!=user); + + $("#post-message button").text(contact==user ? "Post Publicly" : "Post to user") + + this.contact = contact; + this.list.opts.args.contact = contact; + this.list.run(); + + }, + // check for updates every 5 seconds if page is active + refresh: function() { + setTimeout("erpnext.messages.refresh()", 17000); + if(wn.container.page.label != 'Messages') return; + this.show(); + }, + get_contact: function() { + var route = location.hash; + if(route.indexOf('/')!=-1) { + var name = decodeURIComponent(route.split('/')[1]); + if(name.indexOf('__at__')!=-1) { + name = name.replace('__at__', '@'); + } + return name; + } + }, + make_list: function() { + this.list = new wn.ui.Listing({ + parent: $(this.wrapper).find('.all-messages'), + method: 'core.page.messages.messages.get_list', + args: { + contact: null + }, + hide_refresh: true, + no_loading: true, + render_row: function(wrapper, data) { + $(wrapper).removeClass('list-row'); + + data.creation = dateutil.comment_when(data.creation); + data.comment_by_fullname = wn.user_info(data.owner).fullname; + data.image = wn.utils.get_file_link(wn.user_info(data.owner).image); + data.mark_html = ""; + + data.reply_html = ''; + if(data.owner==user) { + data.cls = 'message-self'; + data.comment_by_fullname = 'You'; + } else { + data.cls = 'message-other'; + } + + // delete + data.delete_html = ""; + if(data.owner==user || data.comment.indexOf("assigned to")!=-1) { + data.delete_html = repl('×', data); + } + + if(data.owner==data.comment_docname && data.parenttype!="Assignment") { + data.mark_html = "
" + } + + wrapper.innerHTML = repl('
%(mark_html)s\ + %(comment)s\ + %(delete_html)s\ +
by %(comment_by_fullname)s, %(creation)s
\ +
\ +
', data); + } + }); + }, + delete: function(ele) { + $(ele).parent().css('opacity', 0.6); + wn.call({ + method:'core.page.messages.messages.delete', + args: {name : $(ele).attr('data-name')}, + callback: function() { + $(ele).parent().toggle(false); + } + }); + }, + show_active_users: function() { + var me = this; + wn.call({ + module:'core', + page:'messages', + method:'get_active_users', + callback: function(r,rt) { + var $body = $(me.wrapper).find('.layout-side-section'); + $('

Users


\ +
\ + \ + Show messages from everyone
\ + ').appendTo($body); + r.message.sort(function(a, b) { return b.has_session - a.has_session; }); + for(var i in r.message) { + var p = r.message[i]; + if(p.name != user) { + p.fullname = wn.user_info(p.name).fullname; + p.image = wn.utils.get_file_link(wn.user_info(p.name).image); + p.name = p.name.replace('@', '__at__'); + p.status_color = p.has_session ? "green" : "#ddd"; + p.status = p.has_session ? "Online" : "Offline"; + $(repl('

\ + \ + %(fullname)s\ +

', p)) + .appendTo($body); + } + } + } + }); + } +}); + + diff --git a/core/page/messages/messages.py b/core/page/messages/messages.py new file mode 100644 index 0000000000..90f5e9152f --- /dev/null +++ b/core/page/messages/messages.py @@ -0,0 +1,117 @@ +# ERPNext - web based ERP (http://erpnext.com) +# Copyright (C) 2012 Web Notes Technologies Pvt Ltd +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +from __future__ import unicode_literals +import webnotes + +@webnotes.whitelist() +def get_list(arg=None): + """get list of messages""" + webnotes.form_dict['limit_start'] = int(webnotes.form_dict['limit_start']) + webnotes.form_dict['limit_page_length'] = int(webnotes.form_dict['limit_page_length']) + webnotes.form_dict['user'] = webnotes.session['user'] + + # set all messages as read + webnotes.conn.begin() + webnotes.conn.sql("""UPDATE `tabComment` + set docstatus = 1 where comment_doctype in ('My Company', 'Message') + and comment_docname = %s + """, webnotes.user.name) + webnotes.conn.commit() + + if webnotes.form_dict['contact'] == webnotes.session['user']: + # return messages + return webnotes.conn.sql("""select * from `tabComment` + where (owner=%(contact)s + or comment_docname=%(user)s + or (owner=comment_docname and ifnull(parenttype, "")!="Assignment")) + and comment_doctype ='Message' + order by creation desc + limit %(limit_start)s, %(limit_page_length)s""", webnotes.form_dict, as_dict=1) + else: + return webnotes.conn.sql("""select * from `tabComment` + where (owner=%(contact)s and comment_docname=%(user)s) + or (owner=%(user)s and comment_docname=%(contact)s) + or (owner=%(contact)s and comment_docname=%(contact)s) + and comment_doctype ='Message' + order by creation desc + limit %(limit_start)s, %(limit_page_length)s""", webnotes.form_dict, as_dict=1) + + +@webnotes.whitelist() +def get_active_users(arg=None): + return webnotes.conn.sql("""select name, + (select count(*) from tabSessions where user=tabProfile.name + and timediff(now(), lastupdate) < time("01:00:00")) as has_session + from tabProfile + where ifnull(enabled,0)=1 and + docstatus < 2 and + name not in ('Administrator', 'Guest') + order by first_name""", as_dict=1) + +@webnotes.whitelist() +def post(arg=None): + import webnotes + """post message""" + if not arg: + arg = {} + arg.update(webnotes.form_dict) + + if isinstance(arg, basestring): + import json + arg = json.loads(arg) + + from webnotes.model.doc import Document + d = Document('Comment') + d.parenttype = arg.get("parenttype") + d.comment = arg['txt'] + d.comment_docname = arg['contact'] + d.comment_doctype = 'Message' + d.save() + + import webnotes.utils + if webnotes.utils.cint(arg.get('notify')): + notify(arg) + +@webnotes.whitelist() +def delete(arg=None): + webnotes.conn.sql("""delete from `tabComment` where name=%s""", + webnotes.form_dict['name']); + +def notify(arg=None): + from webnotes.utils import cstr, get_fullname + from startup import get_url + + fn = get_fullname(webnotes.user.name) or webnotes.user.name + + url = get_url() + + message = '''You have a message from %s: + + %s + + To answer, please login to your erpnext account at \ + %s + ''' % (fn, arg['txt'], url, url) + + sender = webnotes.conn.get_value("Profile", webnotes.user.name, "email") \ + or webnotes.user.name + recipient = [webnotes.conn.get_value("Profile", arg["contact"], "email") \ + or arg["contact"]] + + from webnotes.utils.email_lib import sendmail + sendmail(recipient, sender, message, arg.get("subject") or "You have a message from %s" % (fn,)) + \ No newline at end of file diff --git a/core/page/messages/messages.txt b/core/page/messages/messages.txt new file mode 100644 index 0000000000..0949bd7fbb --- /dev/null +++ b/core/page/messages/messages.txt @@ -0,0 +1,32 @@ +[ + { + "creation": "2012-06-14 18:44:56", + "docstatus": 0, + "modified": "2013-04-03 14:48:57", + "modified_by": "Administrator", + "owner": "Administrator" + }, + { + "doctype": "Page", + "module": "Core", + "name": "__common__", + "page_name": "messages", + "standard": "Yes", + "title": "Messages" + }, + { + "doctype": "Page Role", + "name": "__common__", + "parent": "messages", + "parentfield": "roles", + "parenttype": "Page", + "role": "All" + }, + { + "doctype": "Page", + "name": "messages" + }, + { + "doctype": "Page Role" + } +] \ No newline at end of file diff --git a/core/page/modules_setup/__init__.py b/core/page/modules_setup/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/core/page/modules_setup/modules_setup.js b/core/page/modules_setup/modules_setup.js new file mode 100644 index 0000000000..e5de902520 --- /dev/null +++ b/core/page/modules_setup/modules_setup.js @@ -0,0 +1,51 @@ + +wn.pages['modules_setup'].onload = function(wrapper) { + wn.ui.make_app_page({ + parent: wrapper, + title: 'Show or Hide Modules', + single_column: true + }); + + wrapper.appframe.add_button("Update", function() { + wn.modules_setup.update(); + }) + + $('
Select modules to be shown.
').appendTo($(wrapper).find(".layout-main")); + $('
').appendTo($(wrapper).find(".layout-main")); + + wn.modules_setup.refresh_page(); +} + +wn.modules_setup = { + refresh_page: function() { + $('#modules-list').empty(); + + $.each(keys(wn.modules).sort(), function(i, m) { + if(m!="Setup") { + var $chk = $("") + .prependTo($('

'+m+'

').appendTo("#modules-list")); + if(wn.boot.hidden_modules.indexOf(m)==-1) { + $chk.attr("checked", true); + } + } + }); + }, + update: function() { + var ml = []; + $('#modules-list [data-module]:checkbox:not(:checked)').each(function() { + ml.push($(this).attr('data-module')); + }); + + wn.call({ + method: 'core.page.modules_setup.modules_setup.update', + args: { + ml: ml + }, + callback: function(r) { + if(r.exc) msgprint("There were errors.") + }, + btn: this + }); + } + +} \ No newline at end of file diff --git a/core/page/modules_setup/modules_setup.py b/core/page/modules_setup/modules_setup.py new file mode 100644 index 0000000000..e993d83ce3 --- /dev/null +++ b/core/page/modules_setup/modules_setup.py @@ -0,0 +1,9 @@ +from __future__ import unicode_literals +import webnotes + +@webnotes.whitelist() +def update(ml): + """update modules""" + webnotes.conn.set_global('hidden_modules', ml) + webnotes.msgprint('Updated') + webnotes.clear_cache() \ No newline at end of file diff --git a/core/page/modules_setup/modules_setup.txt b/core/page/modules_setup/modules_setup.txt new file mode 100644 index 0000000000..556be2bfb6 --- /dev/null +++ b/core/page/modules_setup/modules_setup.txt @@ -0,0 +1,32 @@ +[ + { + "creation": "2012-10-04 18:45:29", + "docstatus": 0, + "modified": "2013-04-03 12:19:56", + "modified_by": "Administrator", + "owner": "Administrator" + }, + { + "doctype": "Page", + "module": "Core", + "name": "__common__", + "page_name": "modules_setup", + "standard": "Yes", + "title": "Modules Setup" + }, + { + "doctype": "Page Role", + "name": "__common__", + "parent": "modules_setup", + "parentfield": "roles", + "parenttype": "Page", + "role": "System Manager" + }, + { + "doctype": "Page", + "name": "modules_setup" + }, + { + "doctype": "Page Role" + } +] \ No newline at end of file diff --git a/core/page/todo/__init__.py b/core/page/todo/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/core/page/todo/todo.css b/core/page/todo/todo.css new file mode 100644 index 0000000000..f67f729c4f --- /dev/null +++ b/core/page/todo/todo.css @@ -0,0 +1,51 @@ +.todoitem { + padding-bottom: 3px; + clear: both; +} + +.todoitem div { + float: left; + display: inline-block; + padding: 3px; +} + +.todoitem .label { + width: 50px; + margin-right: 11px; + margin-top: 3px; + text-align: center; +} + +.todoitem .todo-date { + margin-top: -2px; + margin-right: 7px; + color: #aaa; +} + +.todoitem .close { + margin-left: 5px; + font-size: 17px; +} + +.todoitem .close-span { + float: right; +} + +.todo-separator { + border-bottom: 1px solid #DEB85F; + margin-bottom: 5px; + clear: both; +} + +.todo-content { + padding-right: 15px; +} + +.todo-layout { + background-color: #FFFDC9; + min-height: 300px; +} + +.todoitem .popup-on-click { + margin: 0px 6px; +} \ No newline at end of file diff --git a/core/page/todo/todo.html b/core/page/todo/todo.html new file mode 100644 index 0000000000..e00f8ef35b --- /dev/null +++ b/core/page/todo/todo.html @@ -0,0 +1,11 @@ +
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file diff --git a/core/page/todo/todo.js b/core/page/todo/todo.js new file mode 100644 index 0000000000..64ab0a3a29 --- /dev/null +++ b/core/page/todo/todo.js @@ -0,0 +1,212 @@ +// ERPNext - web based ERP (http://erpnext.com) +// Copyright (C) 2012 Web Notes Technologies Pvt Ltd +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU 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 General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +wn.provide('erpnext.todo'); + +erpnext.todo.refresh = function() { + wn.call({ + method: 'core.page.todo.todo.get', + callback: function(r,rt) { + var todo_list = $('#todo-list div.todo-content'); + var assigned_todo_list = $('#assigned-todo-list div.todo-content'); + todo_list.empty(); + assigned_todo_list.empty(); + + var nothing_to_do = function() { + $('#todo-list div.todo-content') + .html('
Nothing to do :)
'); + } + + + if(r.message) { + for(var i in r.message) { + new erpnext.todo.ToDoItem(r.message[i]); + } + if (!todo_list.html()) { nothing_to_do(); } + } else { + nothing_to_do(); + } + } + }); +} + +erpnext.todo.ToDoItem = Class.extend({ + init: function(todo) { + label_map = { + 'High': 'label-important', + 'Medium': 'label-info', + 'Low':'' + } + todo.labelclass = label_map[todo.priority]; + todo.userdate = dateutil.str_to_user(todo.date) || ''; + + todo.fullname = ''; + if(todo.assigned_by) { + var assigned_by = wn.boot.user_info[todo.assigned_by] + todo.fullname = repl("[By %(fullname)s] ".bold(), { + fullname: (assigned_by ? assigned_by.fullname : todo.assigned_by), + }); + } + + var parent_list = "#todo-list"; + if(todo.owner !== user) { + var owner = wn.boot.user_info[todo.owner]; + todo.fullname = repl("[To %(fullname)s] ".bold(), { + fullname: (owner ? owner.fullname : todo.owner), + }); + } + parent_list += " div.todo-content"; + + if(todo.reference_name && todo.reference_type) { + todo.link = repl('\ + %(reference_type)s: %(reference_name)s', todo); + } else if(todo.reference_type) { + todo.link = repl('
\ + %(reference_type)s', todo); + } else { + todo.link = ''; + } + if(!todo.description) todo.description = ''; + todo.description_display = todo.description.replace(/\n\n/g, "
").trim(); + + $(parent_list).append(repl('\ +
\ +
%(priority)s
\ + \ +
\ +
%(userdate)s
\ + %(fullname)s:\ +
\ +
%(description_display)s\ + %(link)s\ +
\ + \ +
\ +
', todo)); + $todo = $(parent_list + ' div.todoitem:last'); + + if(todo.checked) { + $todo.find('.description').css('text-decoration', 'line-through'); + } + + if(!todo.reference_type) + $todo.find('.ref_link').toggle(false); + + $todo.find('.popup-on-click') + .data('todo', todo) + .click(function() { + erpnext.todo.make_dialog($(this).data('todo')); + return false; + }); + + $todo.find('.close') + .data('name', todo.name) + .click(function() { + $(this).parent().css('opacity', 0.5); + wn.call({ + method:'core.page.todo.todo.delete', + args: {name: $(this).data('name')}, + callback: function() { + erpnext.todo.refresh(); + } + }); + return false; + }) + } +}); + +erpnext.todo.make_dialog = function(det) { + if(!erpnext.todo.dialog) { + var dialog = new wn.ui.Dialog({ + width: 480, + title: 'To Do', + fields: [ + {fieldtype:'Text', fieldname:'description', label:'Description', + reqd:1}, + {fieldtype:'Date', fieldname:'date', label:'Event Date', reqd:1}, + {fieldtype:'Check', fieldname:'checked', label:'Completed'}, + {fieldtype:'Select', fieldname:'priority', label:'Priority', reqd:1, 'options':['Medium','High','Low'].join('\n')}, + {fieldtype:'Button', fieldname:'save', label:'Save (Ctrl+S)'} + ] + }); + + dialog.fields_dict.save.input.onclick = function() { + erpnext.todo.save(this); + } + erpnext.todo.dialog = dialog; + } + + if(det) { + erpnext.todo.dialog.set_values({ + date: det.date, + priority: det.priority, + description: det.description, + checked: det.checked + }); + erpnext.todo.dialog.det = det; + } + erpnext.todo.dialog.show(); + +} + +erpnext.todo.save = function(btn) { + var d = erpnext.todo.dialog; + var det = d.get_values(); + + if(!det) { + return; + } + + det.name = d.det.name || ''; + wn.call({ + method:'core.page.todo.todo.edit', + args: det, + btn: btn, + callback: function() { + erpnext.todo.dialog.hide(); + erpnext.todo.refresh(); + } + }); +} + +wn.pages.todo.onload = function(wrapper) { + // create app frame + wrapper.appframe = new wn.ui.AppFrame($(wrapper).find('.appframe-area'), 'To Do'); + wrapper.appframe.add_home_breadcrumb(); + wrapper.appframe.add_breadcrumb(wn.modules["To Do"].icon); + wrapper.appframe.add_button('Refresh', erpnext.todo.refresh, 'icon-refresh'); + wrapper.appframe.add_button('Add', function() { + erpnext.todo.make_dialog({ + date:get_today(), priority:'Medium', checked:0, description:''}); + }, 'icon-plus'); + wrapper.appframe.add_ripped_paper_effect(wrapper); + + // show report button for System Manager + if(wn.boot.profile.roles.indexOf("System Manager") !== -1) { + wrapper.appframe.add_button("Report", function() { wn.set_route("query-report", "todo"); }, + "icon-table"); + } + + // load todos + erpnext.todo.refresh(); + + // save on click + wrapper.save_action = function() { + if(erpnext.todo.dialog && erpnext.todo.dialog.display) { + erpnext.todo.dialog.fields_dict.save.input.click(); + } + }; +} \ No newline at end of file diff --git a/core/page/todo/todo.py b/core/page/todo/todo.py new file mode 100644 index 0000000000..f0de04ec9b --- /dev/null +++ b/core/page/todo/todo.py @@ -0,0 +1,64 @@ +# ERPNext - web based ERP (http://erpnext.com) +# Copyright (C) 2012 Web Notes Technologies Pvt Ltd +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +from __future__ import unicode_literals +import webnotes +from webnotes.model.doc import Document + +@webnotes.whitelist() +def get(arg=None): + """get todo list""" + return webnotes.conn.sql("""select name, owner, description, date, + priority, checked, reference_type, reference_name, assigned_by + from `tabToDo` where (owner=%s or assigned_by=%s) + order by field(priority, 'High', 'Medium', 'Low') asc, date asc""", + (webnotes.session['user'], webnotes.session['user']), as_dict=1) + +@webnotes.whitelist() +def edit(arg=None): + import markdown2 + args = webnotes.form_dict + + d = Document('ToDo', args.get('name') or None) + d.description = args['description'] + d.date = args['date'] + d.priority = args['priority'] + d.checked = args.get('checked', 0) + if not d.owner: d.owner = webnotes.session['user'] + d.save(not args.get('name') and 1 or 0) + + if args.get('name') and d.checked: + notify_assignment(d) + + return d.name + +@webnotes.whitelist() +def delete(arg=None): + name = webnotes.form_dict['name'] + d = Document('ToDo', name) + if d and d.name and d.owner != webnotes.session['user']: + notify_assignment(d) + webnotes.conn.sql("delete from `tabToDo` where name = %s", name) + +def notify_assignment(d): + doc_type = d.reference_type + doc_name = d.reference_name + assigned_by = d.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) + \ No newline at end of file diff --git a/core/page/todo/todo.txt b/core/page/todo/todo.txt new file mode 100644 index 0000000000..716f721359 --- /dev/null +++ b/core/page/todo/todo.txt @@ -0,0 +1,32 @@ +[ + { + "creation": "2012-06-14 18:44:56", + "docstatus": 0, + "modified": "2013-04-03 14:44:34", + "modified_by": "Administrator", + "owner": "Administrator" + }, + { + "doctype": "Page", + "module": "Core", + "name": "__common__", + "page_name": "todo", + "standard": "Yes", + "title": "To Do" + }, + { + "doctype": "Page Role", + "name": "__common__", + "parent": "todo", + "parentfield": "roles", + "parenttype": "Page", + "role": "All" + }, + { + "doctype": "Page", + "name": "todo" + }, + { + "doctype": "Page Role" + } +] \ No newline at end of file diff --git a/public/js/wn/app.js b/public/js/wn/app.js index 12ef61a387..1d19142c1b 100644 --- a/public/js/wn/app.js +++ b/public/js/wn/app.js @@ -77,6 +77,7 @@ wn.Application = Class.extend({ load_bootinfo: function() { if(wn.boot) { wn.control_panel = wn.boot.control_panel; + wn.modules = wn.boot.modules; this.set_globals(); this.sync_pages(); diff --git a/public/js/wn/misc/user.js b/public/js/wn/misc/user.js index dbe411d7e5..4f267cce48 100644 --- a/public/js/wn/misc/user.js +++ b/public/js/wn/misc/user.js @@ -53,21 +53,43 @@ $.extend(wn.user, { modules_list.push(m); } }); - } else - // all modules - modules_list = keys(wn.modules); - + } + // filter hidden modules - if(wn.boot.modules_list) { - var allowed_list = JSON.parse(wn.boot.modules_list); - if(modules_list) { - var modules_list = $.map(modules_list, function(m) { - if(allowed_list.indexOf(m)!=-1) return m; else return null; - }); - } else { - var modules_list = allowed_list; - } + if(wn.boot.hidden_modules && modules_list) { + var hidden_list = JSON.parse(wn.boot.hidden_modules); + var modules_list = $.map(modules_list, function(m) { + if(hidden_list.indexOf(m)==-1) return m; else return null; + }); } + + if(!modules_list || !modules_list.length) { + // all modules + modules_list = keys(wn.modules).sort(); + } + + // hide based on permission + modules_list = $.map(modules_list, function(m) { + var type = wn.modules[m] && wn.modules[m].type; + var ret = null; + switch(type) { + case "module": + if(wn.boot.profile.allow_modules.indexOf(m)!=-1) + ret = m; + break; + case "page": + if(wn.boot.allowed_pages.indexOf(wn.modules[m].link)!=-1) + ret = m; + break; + case "view", "setup": + ret = m; + break; + default: + ret = null; + } + return ret; + }) + return modules_list; }, is_report_manager: function() { @@ -75,8 +97,6 @@ $.extend(wn.user, { } }) -// wn.session_alive is true if user shows mouse movement in 30 seconds - wn.session_alive = true; $(document).bind('mousemove', function() { wn.session_alive = true; diff --git a/public/js/wn/views/moduleview.js b/public/js/wn/views/moduleview.js index 8dbf5442a4..f9dff38a9c 100644 --- a/public/js/wn/views/moduleview.js +++ b/public/js/wn/views/moduleview.js @@ -2,7 +2,9 @@ // MIT Licensed. See license.txt wn.provide("wn.views.moduleview"); -wn.provide("wn.model.open_count_conditions") +wn.provide("wn.model.open_count_conditions"); +wn.provide("wn.module_page"); +wn.home_page = "desktop"; wn.views.moduleview.make = function(wrapper, module) { wrapper.module_view = new wn.views.moduleview.ModuleView(wrapper, module); diff --git a/webnotes/__init__.py b/webnotes/__init__.py index 838055e0cc..97581e156f 100644 --- a/webnotes/__init__.py +++ b/webnotes/__init__.py @@ -179,7 +179,6 @@ def get_db_password(db_name): else: return db_name - whitelisted = [] guest_methods = [] def whitelist(allow_guest=False, allow_roles=None): @@ -401,4 +400,18 @@ def repsond_as_web_page(title, html): message = "

" + title + "

" + html response['type'] = 'page' response['page_name'] = 'message.html' + +def get_config(): + import webnotes.utils, json + config = _dict({"modules": {}}) + with open(webnotes.utils.get_path("lib", "config.json"), "r") as configf: + framework_config = json.loads(configf.read()) + config.modules.update(framework_config["modules"]) + + with open(webnotes.utils.get_path("app", "config.json"), "r") as configf: + app_config = json.loads(configf.read()) + config.modules.update(app_config["modules"]) + + return config + \ No newline at end of file diff --git a/webnotes/boot.py b/webnotes/boot.py index f617feee33..0b67ef26f0 100644 --- a/webnotes/boot.py +++ b/webnotes/boot.py @@ -29,6 +29,7 @@ import webnotes import webnotes.defaults import webnotes.model.doc import webnotes.widgets.page +import json def get_bootinfo(): """build and return boot info""" @@ -54,6 +55,8 @@ def get_bootinfo(): bootinfo['sid'] = webnotes.session['sid']; # home page + bootinfo.modules = webnotes.get_config().modules + bootinfo.hidden_modules = webnotes.conn.get_global("hidden_modules") add_home_page(bootinfo, doclist) add_allowed_pages(bootinfo) load_translations(bootinfo) diff --git a/webnotes/utils/__init__.py b/webnotes/utils/__init__.py index 5dd20f8699..f92aaaac3e 100644 --- a/webnotes/utils/__init__.py +++ b/webnotes/utils/__init__.py @@ -785,6 +785,10 @@ def comma_sep(some_list, sep): else: return some_list +def get_path(*path): + import os + return os.path.join(get_base_path(), *path) + def get_base_path(): import conf import os