Merge branch 'master' into edge

This commit is contained in:
Rushabh Mehta 2013-04-03 16:39:02 +05:30
commit cedcb15a70
42 changed files with 1548 additions and 46 deletions

49
config.json Normal file
View file

@ -0,0 +1,49 @@
{
"modules": {
"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"
}
},
"web": {
"pages": {
"404": {
"template": "lib/templates/pages/404"
},
"error": {
"no_cache": true,
"template": "lib/templates/pages/error"
},
"login": {
"template": "lib/templates/pages/login"
},
"message": {
"no_cache": true,
"template": "lib/templates/pages/message"
},
"print": {
"no_cache": true,
"template": "lib/templates/pages/print",
"args_method": "core.doctype.print_format.print_format.get_args"
}
},
"generators": {}
}
}

View file

@ -8,7 +8,7 @@ from webnotes.utils import cstr, cint, flt
from webnotes.utils.datautils import UnicodeWriter
data_keys = webnotes._dict({
"data_separator": '::: Start entering data below this line :::',
"data_separator": 'Start entering data below this line',
"main_table": "Table:",
"parent_table": "Parent Table:",
"columns": "Column Name:"
@ -68,7 +68,7 @@ def get_template():
else:
w.writerow([''])
w.writerow([':::'])
w.writerow([''])
w.writerow(['Notes:'])
w.writerow(['Please do not change the template headings.'])
w.writerow(['First data column must be blank.'])
@ -80,7 +80,7 @@ def get_template():
if key == "parent":
w.writerow(['"Parent" signifies the parent table in which this row must be added'])
w.writerow(['If you are updating, please select "Overwrite" else existing rows will not be deleted.'])
w.writerow([':::'])
w.writerow([''])
labelrow = ["Column Labels", "ID"]
fieldrow = [data_keys.columns, key]
mandatoryrow = ['Mandatory:', 'Yes']

View file

View file

@ -0,0 +1,83 @@
.case-border {
border-radius: 10px;
-moz-border-radius: 10px;
-webkit-border-radius: 10px;
width: 32px;
height: 32px;
padding: 12px;
border: 2px solid white;
box-shadow: 0 0 4px 1px black;
-moz-box-shadow: 0 0 4px 1px black;
-webkit-box-shadow: 0 0 4px 1px black;
-o-box-shadow: 0 0 4px 1px black;
margin: auto;
}
.case-wrapper {
margin: 24px;
float: left;
width: 100px;
height: 100px;
}
.case-wrapper i {
font-size: 32px;
color: #f8f8f8;
}
.case-label {
color: white;
padding-top: 10px;
text-align: center;
text-shadow: 1px 1px 2px #000, 1px 1px 2px #000, 1px 1px 2px #000, 0px 0px 2px #000;
}
/* Hover and click effects */
.case-border:hover, .circle:hover, .hover-effect {
box-shadow: 0 0 2px 0px black, 0 0 4px 1px white !important;
-moz-box-shadow: 0 0 2px 0px black, 0 0 4px 1px white !important;
-webkit-box-shadow: 0 0 2px 0px black, 0 0 4px 1px white !important;
-o-box-shadow: 0 0 2px 0px black, 0 0 10px 1px white !important;
}
.case-border:active, .case-border:focus, .case-border-click {
transform: scale(0.98, 0.98);
-ms-transform: scale(0.98, 0.98); /* IE 9 */
-webkit-transform: scale(0.98, 0.98); /* Safari and Chrome */
-o-transform: scale(0.98, 0.98); /* Opera */
-moz-transform: scale(0.98, 0.98); /* Firefox */
}
.circle:active, .circle:focus, .circle-click {
transform: scale(1, 1);
-ms-transform: scale(1, 1); /* IE 9 */
-webkit-transform: scale(1, 1); /* Safari and Chrome */
-o-transform: scale(1, 1); /* Opera */
-moz-transform: scale(1, 1); /* Firefox */
}
.circle {
border-radius: 30px;
-moz-border-radius: 30px;
-webkit-border-radius: 30px;
height: 15px;
line-height: 12px;
min-width: 15px;
background: #B00D07;
padding: 3px;
float: right;
margin-top: -12px;
margin-right: 10px;
border: 2px solid white;
box-shadow: 0 0 4px 1px black;
-moz-box-shadow: 0 0 4px 1px black;
-webkit-box-shadow: 0 0 4px 1px black;
-o-box-shadow: 0 0 4px 1px black;
}
.circle-text {
color: white;
text-align: center;
display: inline-block;
margin-top: 1px;
}

View file

@ -0,0 +1,6 @@
<div style="min-height: 500px; background: None; text-align: center;
margin: 0px auto;">
<div id="icon-grid">
</div>
</div>
<div style="clear: both"></div>

View file

@ -0,0 +1,101 @@
wn.provide('erpnext.desktop');
erpnext.desktop.refresh = function() {
erpnext.desktop.render();
$("#icon-grid").sortable({
update: function() {
new_order = [];
$("#icon-grid .case-wrapper").each(function(i, e) {
new_order.push($(this).attr("data-name"));
});
wn.defaults.set_default("_desktop_items", new_order);
}
});
}
erpnext.desktop.render = function() {
document.title = "Desktop";
var add_icon = function(m) {
var module = wn.modules[m];
if(!module.label)
module.label = m;
module.name = m;
module.label = wn._(module.label);
module.gradient_css = wn.get_gradient_css(module.color, 45);
module._link = module.link.toLowerCase().replace("/", "-");
$module_icon = $(repl('\
<div id="module-icon-%(_link)s" class="case-wrapper" \
data-name="%(name)s" data-link="%(link)s">\
<div class="case-border" style="%(gradient_css)s">\
<i class="%(icon)s"></i>\
</div>\
<div class="case-label">%(label)s</div>\
</div>', module)).click(function() {
wn.set_route($(this).attr("data-link"));
}).css({
cursor:"pointer"
}).appendTo("#icon-grid");
}
// modules
var modules_list = wn.user.get_desktop_items();
$.each(modules_list, function(i, m) {
if(m!="Setup")
add_icon(m);
})
// setup
if(user_roles.indexOf('System Manager')!=-1)
add_icon('Setup')
// notifications
erpnext.desktop.show_pending_notifications();
}
erpnext.desktop.show_pending_notifications = function() {
var add_circle = function(str_module, id, title) {
var module = $('#'+str_module);
module.prepend(
repl('<div id="%(id)s" class="circle" title="%(title)s" style="display: None">\
<span class="circle-text"></span>\
</div>', {id: id, title: wn._(title)}));
var case_border = module.find('.case-border');
var circle = module.find('.circle');
var add_hover_and_click = function(primary, secondary, hover_class, click_class) {
primary
.hover(
function() { secondary.addClass(hover_class); },
function() { secondary.removeClass(hover_class); })
.mousedown(function() { secondary.addClass(click_class); })
.mouseup(function() { secondary.removeClass(click_class); })
.focusin(function() { $(this).mousedown(); })
.focusout(function() { $(this).mouseup(); })
}
add_hover_and_click(case_border, circle, 'hover-effect', 'circle-click');
add_hover_and_click(circle, case_border, 'hover-effect', 'case-border-click');
}
add_circle('module-icon-messages', 'unread_messages', 'Unread Messages');
add_circle('module-icon-support-home', 'open_support_tickets', 'Open Support Tickets');
add_circle('module-icon-todo', 'things_todo', 'Things To Do');
add_circle('module-icon-calendar-event', 'todays_events', 'Todays Events');
add_circle('module-icon-projects-home', 'open_tasks', 'Open Tasks');
add_circle('module-icon-questions', 'unanswered_questions', 'Unanswered Questions');
add_circle('module-icon-selling-home', 'open_leads', 'Open Leads');
erpnext.update_messages();
}
pscript.onload_desktop = function() {
// load desktop
erpnext.desktop.refresh();
}

View file

@ -0,0 +1,32 @@
[
{
"creation": "2013-02-14 17:37:37",
"docstatus": 0,
"modified": "2013-04-03 11:38:05",
"modified_by": "Administrator",
"owner": "Administrator"
},
{
"doctype": "Page",
"module": "Core",
"name": "__common__",
"page_name": "desktop",
"standard": "Yes",
"title": "Desktop"
},
{
"doctype": "Page Role",
"name": "__common__",
"parent": "desktop",
"parentfield": "roles",
"parenttype": "Page",
"role": "All"
},
{
"doctype": "Page",
"name": "desktop"
},
{
"doctype": "Page Role"
}
]

View file

View 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;
}

View file

View 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">&times;</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);
}
}
}
});
}
});

View 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,))

View 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"
}
]

View file

View 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
});
}
}

View 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()

View 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"
}
]

View file

51
core/page/todo/todo.css Normal file
View 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
View 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
View 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">&times;</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
View 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
View 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"
}
]

View file

@ -29,20 +29,34 @@ wn.UpdateThisApp = Class.extend({
this.wrapper.appframe.add_button(wn._("Get Latest Updates"),
function() { me.update_this_app(this); }, "icon-rss");
this.wrapper.update_output = $('<pre class="well update-output"></pre>')
.appendTo(this.body.append("<div></div>"));
this.wrapper.update_output.text(wn._('Click on "Get Latest Updates"'));
this.wrapper.update_output = $('<pre class="update-output"></pre>')
.appendTo(this.body);
this.wrapper.update_output.toggle(false);
this.wrapper.progress_bar = $('<div class="app-update-progress-bar well"></div>')
.appendTo(this.body);
this.wrapper.progress_bar.text(wn._('Click on "Get Latest Updates"'));
}
},
update_this_app: function(btn) {
var me = this;
me.wrapper.update_output.toggle(false);
me.wrapper.progress_bar.empty().toggle(true);
this.wrapper.progress_bar.html('<div class="progress progress-striped active"> \
<div class="bar" style="width: 100%;"></div> \
</div> \
<div>' + wn._("Update is in progress. This may take some time.") + '</div>');
wn.call({
module: "core",
page: "update_manager",
method: "update_this_app",
callback: function(r) {
me.wrapper.update_output.toggle(true);
me.wrapper.progress_bar.empty().toggle(false);
me.wrapper.update_output.text(r.message);
},
btn: btn,

View file

@ -425,7 +425,9 @@ function DataField() { } DataField.prototype = new Field();
DataField.prototype.make_input = function() {
var me = this;
this.input = $a_input(this.input_area, this.df.fieldtype=='Password' ? 'password' : 'text');
if(this.df.placeholder) $(this.input).attr("placeholder", this.df.placeholder);
this.get_value= function() {
var v = this.input.value;
if(this.validate)
@ -894,10 +896,16 @@ FloatField.prototype.format_input = function() {
this.input.value='';
else {
var format;
if(this.get_field_currency)
if(this.get_field_currency) {
format = get_number_format(this.get_field_currency());
this.input.value =
format_number(parseFloat(this.input.value), format);
this.input.value =
format_number(parseFloat(this.input.value), format);
} else {
var decimals = wn.boot.sysdefaults.float_precision ?
parseInt(wn.boot.sysdefaults.float_precision) : null;
this.input.value = format_number(parseFloat(this.input.value), null, decimals);
}
}
}
FloatField.prototype.onmake_input = function() {

View file

@ -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();

View file

@ -11,7 +11,7 @@ wn.form.formatters = {
parseInt(wn.boot.sysdefaults.float_precision) : null;
return "<div style='text-align: right'>" +
format_number(flt(value, decimals), null, decimals) + "</div>";
format_number(value, null, decimals) + "</div>";
},
Int: function(value) {
return cint(value);

View file

@ -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;

View file

@ -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);

View file

@ -120,6 +120,7 @@ wn.views.QueryReport = Class.extend({
$.each(wn.query_reports[this.report_name].filters || [], function(i, df) {
var f = make_field(df, null, $filter_wrapper.get(0), null, 0, 1);
f.df.single_select = 1;
f.df.placeholder = df.label;
f.not_in_form = 1;
f.with_label = 0;
f.in_filter = 1;

25
templates/base.html Normal file
View file

@ -0,0 +1,25 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{ title }}</title>
<meta name="generator" content="wnframework">
<script type="text/javascript" src="lib/js/lib/jquery/jquery.min.js"></script>
<script type="text/javascript" src="js/all-web.min.js"></script>
<script type="text/javascript" src="js/wn-web.js"></script>
<link type="text/css" rel="stylesheet" href="css/all-web.css">
<link type="text/css" rel="stylesheet" href="css/wn-web.css">
<link rel="shortcut icon" href="{{ favicon }}" type="image/x-icon">
<link rel="icon" href="{{ favicon }}" type="image/x-icon">
{% if description -%}
<meta name="description" content="{{ description }}">
{%- endif %}
{% block header -%}
{%- endblock %}
</head>
<body>
{% block body %}
{% endblock %}
</body>
</html>

43
templates/css/login.css Normal file
View file

@ -0,0 +1,43 @@
<style>
#login_wrapper {
width: 300px;
margin: 70px auto;
}
#login_wrapper,
#login_wrapper h3 {
color: #333;
}
#login_wrapper a {
color: #0088cc;
}
.layout-wrapper {
background-color: #fff;
padding: 10px;
box-shadow: 1px 1px 3px 3px #ccc;
font-size: 12px;
min-height: 100px;
border-radius: 5px;
}
#login_wrapper h3 {
text-align: center;
}
.login-banner {
margin-bottom: 20px;
}
.login-box td {
padding: 8px;
}
.login-box td input {
margin-bottom: 0px;
}
.login-footer {
text-align: center;
padding: 15px;
}
</style>

97
templates/js/login.js Normal file
View file

@ -0,0 +1,97 @@
var login = {};
$(document).ready(function(wrapper) {
$('#login_btn').click(login.do_login)
$('#password').keypress(function(ev){
if(ev.which==13 && $('#password').val()) {
$('form').submit(function() {
login.do_login();
return false;
});
}
});
$(document).trigger('login_rendered');
})
// Login
login.do_login = function(){
var args = {};
if(window.is_sign_up) {
args.cmd = "core.doctype.profile.profile.sign_up";
args.email = $("#login_id").val();
args.full_name = $("#full_name").val();
if(!args.email || !valid_email(args.email) || !args.full_name) {
login.set_message("Valid email and name required.");
return false;
}
} else if(window.is_forgot) {
args.cmd = "reset_password";
args.user = $("#login_id").val();
if(!args.user) {
login.set_message("Valid Login Id required.");
return false;
}
} else {
args.cmd = "login"
args.usr = $("#login_id").val();
args.pwd = $("#password").val();
if(!args.usr || !args.pwd) {
login.set_message("Both login and password required.");
return false;
}
}
$('#login_btn').attr("disabled", "disabled");
$("#login-spinner").toggle(true);
$('#login_message').toggle(false);
$.ajax({
type: "POST",
url: "server.py",
data: args,
dataType: "json",
success: function(data) {
$("input").val("");
$("#login-spinner").toggle(false);
$('#login_btn').attr("disabled", false);
if(data.message=="Logged In") {
window.location.href = "app.html";
} else if(data.message=="No App") {
window.location.href = "index";
} else {
login.set_message(data.message);
}
}
})
return false;
}
login.sign_up = function() {
$("#login_wrapper h3").html("Sign Up");
$("#login-label").html("Email Id");
$("#password-row, #sign-up-wrapper, #login_message").toggle(false);
$("#full-name-row").toggle(true);
$("#login_btn").html("Register");
$("#forgot-wrapper").html("<a onclick='location.reload()' href='#'>Login</a>")
window.is_sign_up = true;
}
login.show_forgot_password = function() {
$("#login_wrapper h3").html("Forgot");
$("#login-label").html("Email Id");
$("#password-row, #sign-up-wrapper, #login_message").toggle(false);
$("#login_btn").html("Send Password");
$("#forgot-wrapper").html("<a onclick='location.reload()' href='#'>Login</a>")
window.is_forgot = true;
}
login.set_message = function(message, color) {
$('#login_message').html(message).toggle(true);
}

14
templates/pages/404.html Normal file
View file

@ -0,0 +1,14 @@
{% extends "app/website/templates/html/outer.html" %}
{% set title="Not Found" %}
{% block content %}
<div class="content">
<div class="layout-wrapper layout-main">
<h3><i class="icon-exclamation-sign"></i> Page missing or moved</h3>
<br>
<p>We are very sorry for this, but the page you are looking for is missing
(this could be because of a typo in the address) or moved.</p>
</div>
</div>
{% endblock %}

View file

@ -0,0 +1,13 @@
{% extends "lib/templates/base.html" %}
{% set title="Error" %}
{% block body %}
<div class="container">
<div class="outer well">
<h3><i class="icon-exclamation-sign"></i> Oops, a server error has occured</h3>
<br>
<pre>%(error)s</pre>
</div>
</div>
{% endblock %}

View file

@ -0,0 +1,62 @@
{% extends "lib/templates/base.html" %}
{% block header %}
<script>
{% include "lib/templates/js/login.js" %}
</script>
{% include "lib/templates/css/login.css" %}
{% endblock %}
{% set title="Login" %}
{% block body %}
<div class="container" id='login_wrapper'>
<div class='layout-wrapper layout-main'>
<p id="login_message" class="alert" style="display: none;"></p>
<h3><i class="icon-lock" style="margin-top: 7px"></i> Login</h3>
<form autocomplete="on">
<table border="0" class="login-box">
<tbody>
<tr>
<td style="text-align: right; padding: 3px;"
id="login-label">Login Id</td>
<td><input id="login_id" type="text" style="width: 180px"/></td>
</tr>
<tr id="password-row">
<td style="text-align: right; padding: 3px;" >Password</td>
<td><input id="password" type="password" style="width: 180px" /></td>
</tr>
<tr id="full-name-row" style="display: none;">
<td style="text-align: right; padding: 3px;">Full Name</td>
<td><input id="full_name" type="text" style="width: 180px" /></td>
</tr>
<tr>
<td>&nbsp;</td>
<td>
<button type="submit" id="login_btn"
class="btn btn-small btn-primary">Login</button>
<img src="lib/images/ui/button-load.gif" id="login-spinner"
style="display: none;">
</td>
</tr>
</tbody>
</table>
</form>
<br>
<p style="text-align: center" id="forgot-wrapper">
<a id="forgot-password" style="cursor:pointer"
onclick="return login.show_forgot_password()">Forgot Password</a></p>
<p style="text-align: center" id="sign-up-wrapper">
New user? <a id="sign-up" style="cursor:pointer"
onclick="return login.sign_up()">Sign Up</a></p>
</div>
</div>
<div class="web-footer login-footer container">
<a href="index.html">Home</a> |
<a href="https://erpnext.com">ERPNext</a><br><br>
{% if copyright %}
<div class="web-footer-copyright">&copy; {{ copyright }}
{% endif %}
</div>
{% endblock %}

View file

@ -0,0 +1,11 @@
{% extends "lib/templates/base.html" %}
{% set title=webnotes.message_title %}
{% block block %}
<div class="container">
<div class="outer well">
{{ webnotes.message }}
</div>
</div>
{% endblock %}

View file

@ -0,0 +1,18 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Print Format</title>
<meta name="generator" content="wnframework">
<style>
{{ css }}
</style>
</head>
<body>
{{ body }}
</body>
{%- if comment -%}
<!-- {{ comment }} -->
{%- endif -%}
</html>

View file

@ -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,25 @@ def repsond_as_web_page(title, html):
message = "<h3>" + title + "</h3>" + html
response['type'] = 'page'
response['page_name'] = 'message.html'
_config = None
def get_config():
global _config
if not _config:
import webnotes.utils, json
_config = _dict({"modules": {}, "web": _dict({"pages": {}, "generators": {}})})
with open(webnotes.utils.get_path("lib", "config.json"), "r") as configf:
framework_config = json.loads(configf.read())
_config.modules.update(framework_config["modules"])
_config.web.pages.update(framework_config["web"]["pages"])
_config.web.generators.update(framework_config["web"]["generators"])
with open(webnotes.utils.get_path("app", "config.json"), "r") as configf:
app_config = json.loads(configf.read())
_config.modules.update(app_config["modules"])
_config.web.pages.update(app_config["web"]["pages"])
_config.web.generators.update(app_config["web"]["generators"])
return _config

View file

@ -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)

View file

@ -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

View file

@ -76,8 +76,8 @@ def update_page_name(doc, title):
"""set page_name and check if it is unique"""
webnotes.conn.set(doc, "page_name", page_name(title))
if doc.page_name in standard_pages:
webnotes.conn.sql("""Page Name cannot be one of %s""" % ', '.join(standard_pages))
if doc.page_name in get_standard_pages():
webnotes.conn.sql("""Page Name cannot be one of %s""" % ', '.join(get_standard_pages()))
res = webnotes.conn.sql("""\
select count(*) from `tab%s`
@ -103,26 +103,35 @@ def build_html(args):
args["len"] = len
jenv = Environment(loader = FileSystemLoader(get_templates_path()))
html = jenv.get_template(args['template']).render(args)
jenv = Environment(loader = FileSystemLoader(webnotes.utils.get_base_path()))
template_name = args['template']
if not template_name.endswith(".html"):
template_name = template_name + ".html"
html = jenv.get_template(template_name).render(args)
return html
def get_standard_pages():
return webnotes.get_config()["web"]["pages"].keys()
def prepare_args(page_name):
if page_name == 'index':
page_name = get_home_page()
if page_name in standard_pages:
pages = get_page_settings()
if page_name in pages:
page_info = pages[page_name]
args = webnotes._dict({
'template': 'pages/%s.html' % page_name,
'template': page_info["template"],
'name': page_name,
})
if page_name in page_settings_map:
target = page_settings_map[page_name]
if "." in target:
args.update(webnotes.get_method(target)())
else:
args.obj = webnotes.bean(page_settings_map[page_name]).obj
# additional args
if "args_method" in page_info:
args.update(webnotes.get_method(page_info["args_method"])())
elif "args_doctype" in page_info:
args.obj = webnotes.bean(page_info["args_doctype"]).obj
else:
args = get_doc_fields(page_name)
@ -145,7 +154,7 @@ def get_doc_fields(page_name):
obj.prepare_template_args()
args = obj.doc.fields
args['template'] = page_map[doc_type].template
args['template'] = get_generators()[doc_type]["template"]
args['obj'] = obj
args['int'] = int
@ -153,10 +162,10 @@ def get_doc_fields(page_name):
def get_source_doc(page_name):
"""get source doc for the given page name"""
for doctype in page_map:
for doctype in get_generators():
name = webnotes.conn.sql("""select name from `tab%s` where
page_name=%s and ifnull(%s, 0)=1""" % (doctype, "%s",
page_map[doctype].condition_field), page_name)
get_generators()[doctype]["condition_field"]), page_name)
if name:
return doctype, name[0][0]
@ -171,9 +180,8 @@ def clear_cache(page_name=None):
cache.delete_value("page:" + p)
def get_all_pages():
all_pages = standard_pages
all_pages += page_settings_map.keys()
for doctype in page_map:
all_pages = get_standard_pages()
for doctype in get_generators():
all_pages += [p[0] for p in webnotes.conn.sql("""select distinct page_name
from `tab%s`""" % doctype) if p[0]]
@ -208,4 +216,14 @@ def get_hex_shade(color, percent):
percent = percent * 2
return p(r) + p(g) + p(b)
def get_standard_pages():
return webnotes.get_config()["web"]["pages"].keys()
def get_generators():
return webnotes.get_config()["web"]["generators"]
def get_page_settings():
return webnotes.get_config()["web"]["pages"]