[framework] [cleanup] desktop, todo, messages, modules setup moved to framework
This commit is contained in:
parent
1fa47cff6f
commit
3211552c06
24 changed files with 950 additions and 18 deletions
32
config.json
Normal file
32
config.json
Normal file
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
})
|
||||
|
||||
|
|
|
|||
0
core/page/messages/__init__.py
Normal file
0
core/page/messages/__init__.py
Normal file
32
core/page/messages/messages.css
Normal file
32
core/page/messages/messages.css
Normal file
|
|
@ -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;
|
||||
}
|
||||
0
core/page/messages/messages.html
Normal file
0
core/page/messages/messages.html
Normal file
214
core/page/messages/messages.js
Normal file
214
core/page/messages/messages.js
Normal file
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
wn.provide('erpnext.messages');
|
||||
|
||||
wn.pages.messages.onload = function(wrapper) {
|
||||
wn.ui.make_app_page({
|
||||
parent: wrapper,
|
||||
title: "Messages"
|
||||
});
|
||||
|
||||
$('<div><div class="avatar avatar-large">\
|
||||
<img id="avatar-image" src="lib/images/ui/avatar.png"></div>\
|
||||
<h3 style="display: inline-block" id="message-title">Everyone</h3>\
|
||||
</div><hr>\
|
||||
<div id="post-message">\
|
||||
<textarea style="width: 100%; height: 24px;"></textarea>\
|
||||
<div><button class="btn">Post</button></div><hr>\
|
||||
</div>\
|
||||
<div class="all-messages"></div>').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('<a class="close" \
|
||||
onclick="erpnext.messages.delete(this)"\
|
||||
data-name="%(name)s">×</a>', data);
|
||||
}
|
||||
|
||||
if(data.owner==data.comment_docname && data.parenttype!="Assignment") {
|
||||
data.mark_html = "<div class='message-mark' title='Public'\
|
||||
style='background-color: green'></div>"
|
||||
}
|
||||
|
||||
wrapper.innerHTML = repl('<div class="message %(cls)s">%(mark_html)s\
|
||||
<span class="avatar avatar-small"><img src="%(image)s"></span><b>%(comment)s</b>\
|
||||
%(delete_html)s\
|
||||
<div class="help">by %(comment_by_fullname)s, %(creation)s</div>\
|
||||
</div>\
|
||||
<div style="clear: both;"></div>', 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');
|
||||
$('<h4>Users</h4><hr>\
|
||||
<div id="show-everyone">\
|
||||
<a href="#messages/'+user+'" class="btn">\
|
||||
Show messages from everyone</a><hr></div>\
|
||||
').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('<p>\
|
||||
<span class="avatar avatar-small" \
|
||||
style="border: 3px solid %(status_color)s" \
|
||||
title="%(status)s"><img src="%(image)s"></span>\
|
||||
<a href="#!messages/%(name)s">%(fullname)s</a>\
|
||||
</p>', p))
|
||||
.appendTo($body);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
117
core/page/messages/messages.py
Normal file
117
core/page/messages/messages.py
Normal file
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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 <b>%s</b>:
|
||||
|
||||
%s
|
||||
|
||||
To answer, please login to your erpnext account at \
|
||||
<a href=\"%s\" target='_blank'>%s</a>
|
||||
''' % (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,))
|
||||
|
||||
32
core/page/messages/messages.txt
Normal file
32
core/page/messages/messages.txt
Normal file
|
|
@ -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"
|
||||
}
|
||||
]
|
||||
0
core/page/modules_setup/__init__.py
Normal file
0
core/page/modules_setup/__init__.py
Normal file
51
core/page/modules_setup/modules_setup.js
Normal file
51
core/page/modules_setup/modules_setup.js
Normal file
|
|
@ -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();
|
||||
})
|
||||
|
||||
$('<div class="alert">Select modules to be shown.</div>').appendTo($(wrapper).find(".layout-main"));
|
||||
$('<div id="modules-list">').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 = $("<input type='checkbox' data-module='"+m+"' style='margin-top: -2px'>")
|
||||
.prependTo($('<p><span> '+m+'</span></p>').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
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
9
core/page/modules_setup/modules_setup.py
Normal file
9
core/page/modules_setup/modules_setup.py
Normal file
|
|
@ -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()
|
||||
32
core/page/modules_setup/modules_setup.txt
Normal file
32
core/page/modules_setup/modules_setup.txt
Normal file
|
|
@ -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"
|
||||
}
|
||||
]
|
||||
0
core/page/todo/__init__.py
Normal file
0
core/page/todo/__init__.py
Normal file
51
core/page/todo/todo.css
Normal file
51
core/page/todo/todo.css
Normal file
|
|
@ -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;
|
||||
}
|
||||
11
core/page/todo/todo.html
Normal file
11
core/page/todo/todo.html
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
<div class="layout-wrapper layout-wrapper-background">
|
||||
<div class="appframe-area"></div>
|
||||
<div class="layout-main todo-layout">
|
||||
<div>
|
||||
<div id="todo-list">
|
||||
<div class="todo-content"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="clear: both"></div>
|
||||
</div>
|
||||
</div>
|
||||
212
core/page/todo/todo.js
Normal file
212
core/page/todo/todo.js
Normal file
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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('<div class="alert">Nothing to do :)</div>');
|
||||
}
|
||||
|
||||
|
||||
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('<a href="#!Form/%(reference_type)s/%(reference_name)s">\
|
||||
%(reference_type)s: %(reference_name)s</a>', todo);
|
||||
} else if(todo.reference_type) {
|
||||
todo.link = repl('<br><a href="#!List/%(reference_type)s">\
|
||||
%(reference_type)s</a>', todo);
|
||||
} else {
|
||||
todo.link = '';
|
||||
}
|
||||
if(!todo.description) todo.description = '';
|
||||
todo.description_display = todo.description.replace(/\n\n/g, "<br>").trim();
|
||||
|
||||
$(parent_list).append(repl('\
|
||||
<div class="todoitem">\
|
||||
<div class="label %(labelclass)s">%(priority)s</div>\
|
||||
<div class="popup-on-click"><a href="#">[edit]</a></div>\
|
||||
<div class="todo-date-fullname">\
|
||||
<div class="todo-date">%(userdate)s</div>\
|
||||
%(fullname)s:\
|
||||
</div>\
|
||||
<div class="description">%(description_display)s\
|
||||
<span class="ref_link">%(link)s</span>\
|
||||
</div>\
|
||||
<div class="close-span"><a href="#" class="close">×</a></div>\
|
||||
</div>\
|
||||
<div class="todo-separator"></div>', 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();
|
||||
}
|
||||
};
|
||||
}
|
||||
64
core/page/todo/todo.py
Normal file
64
core/page/todo/todo.py
Normal file
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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)
|
||||
|
||||
32
core/page/todo/todo.txt
Normal file
32
core/page/todo/todo.txt
Normal file
|
|
@ -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"
|
||||
}
|
||||
]
|
||||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 = "<h3>" + title + "</h3>" + 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
|
||||
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue