Selaa lähdekoodia

Merge branch 'live' of github.com:webnotes/wnframework into live

version-14
Nabin Hait 14 vuotta sitten
vanhempi
commit
4408cf2f9f
31 muutettua tiedostoa jossa 790 lisäystä ja 982 poistoa
  1. +250
    -228
      cgi-bin/core/doctype/doctype_mapper/doctype_mapper.py
  2. +9
    -0
      cgi-bin/core/doctype/event/event.js
  3. +14
    -0
      cgi-bin/core/doctype/file/file.py
  4. +103
    -423
      cgi-bin/core/doctype/profile/profile.txt
  5. +8
    -66
      cgi-bin/core/doctype/search_criteria/search_criteria.txt
  6. +3
    -1
      cgi-bin/core/doctype/system_console/system_console.js
  7. +14
    -1
      cgi-bin/webnotes/__init__.py
  8. +33
    -10
      cgi-bin/webnotes/auth.py
  9. +12
    -5
      cgi-bin/webnotes/db.py
  10. +5
    -1
      cgi-bin/webnotes/model/__init__.py
  11. +28
    -29
      cgi-bin/webnotes/model/doclist.py
  12. +59
    -40
      cgi-bin/webnotes/model/utils.py
  13. +15
    -12
      cgi-bin/webnotes/modules/__init__.py
  14. +4
    -3
      cgi-bin/webnotes/modules/patch.py
  15. +6
    -2
      cgi-bin/webnotes/utils/__init__.py
  16. +14
    -1
      cgi-bin/webnotes/utils/backups.py
  17. +9
    -3
      cgi-bin/webnotes/utils/email_lib/receive.py
  18. +1
    -1
      cgi-bin/webnotes/utils/scheduler.py
  19. +1
    -1
      cgi-bin/webnotes/widgets/page.py
  20. +48
    -48
      cgi-bin/webnotes/widgets/query_builder.py
  21. +9
    -9
      cgi-bin/webnotes/widgets/search.py
  22. +25
    -5
      cgi-bin/webnotes/widgets/tags.py
  23. +17
    -14
      js/form.compressed.js
  24. +1
    -1
      js/webpage/page.js
  25. +35
    -28
      js/webpage/search.js
  26. +5
    -0
      js/widgets/form/form.js
  27. +4
    -1
      js/widgets/form/form_fields.js
  28. +6
    -7
      js/widgets/form/form_grid.js
  29. +42
    -38
      js/widgets/form/grid.js
  30. +7
    -1
      js/widgets/report_builder/report_builder.js
  31. +3
    -3
      js/wnf.compressed.js

+ 250
- 228
cgi-bin/core/doctype/doctype_mapper/doctype_mapper.py Näytä tiedosto

@@ -2,7 +2,7 @@
import webnotes

from webnotes.utils import add_days, add_months, add_years, cint, cstr, date_diff, default_fields, flt, fmt_money, formatdate, generate_hash, getTraceback, get_defaults, get_first_day, get_last_day, getdate, has_common, month_name, now, nowdate, replace_newlines, sendmail, set_default, str_esc_quote, user_format, validate_email_add
from webnotes.model import db_exists
from webnotes.model import db_exists, default_fields
from webnotes.model.doc import Document, addchild, removechild, getchildren, make_autoname, SuperDocType
from webnotes.model.doclist import getlist, copy_doclist
from webnotes.model.code import get_obj, get_server_obj, run_server_obj, updatedb, check_syntax
@@ -18,230 +18,252 @@ convert_to_lists = webnotes.conn.convert_to_lists


class DocType:
def __init__(self, doc, doclist=[]):
self.doc = doc
self.doclist = doclist
self.prefix = is_testing and 'test' or 'tab'
self.ref_doc = ''
# Autoname
#---------
def autoname(self):
self.doc.name = make_autoname(self.doc.from_doctype + '-' + self.doc.to_doctype)

# Map Custom Fields
# ------------------
def map_custom_fields(self, from_doctype, to_doctype, from_doc, to_doc):
fld_list = []
for d in sql("select fieldname from `tabCustom Field` where dt = %s and docstatus != 2",from_doctype):
if sql("select fieldname from `tabCustom Field` where dt = %s and fieldname = %s and docstatus != 2",(to_doctype, d[0])):
fld_list.append([d[0], d[0]])
self.set_value(fld_list, from_doc, to_doc)

# Maps the fields in 'To DocType'
#--------------------------------
def dt_map(self, from_doctype, to_doctype, from_docname, to_doc, doclist, from_to_list = '[]'):

# definition of arguments
'''
String <from_doctype> : contains the name of DocType initiating the function
String <to_doctype> : contains the name of DocType created by the function
String <from_docname> : contains ID(name) of 'from_doctype'
String <to_doc> : contains doc of 'to_doctype'
String <doclist> : contains doclist of 'to_doctype'
String <from_to_list> : contains list of tables which will be mapped
'''
# Validate reference doc docstatus
self.ref_doc = from_docname
self.check_ref_docstatus()
if not doclist:
doclist.append(to_doc)

tbl_list = sql("select from_table, to_table, from_field, to_field, match_id, validation_logic from `tabTable Mapper Detail` where parent ='%s' order by match_id" % (from_doctype + "-" + to_doctype))

for t in tbl_list:
from_table_name = t[0]
to_table_name = t[1]
from_table_fname = t[2]
to_table_fname = t[3]
match_id = t[4]
validation_logic = t[5]

from_to = [from_table_name, to_table_name]

if from_to in eval(from_to_list):
fld_list = sql("select from_field, to_field from `tabField Mapper Detail` where parent = '%s' and match_id = %s and map = 'Yes'" % (from_doctype + "-" + to_doctype, match_id))
if fld_list:
if not from_docname:
msgprint(from_doctype + " not selected for mapping")
raise Exception
# Parent to parent mapping
if from_table_name == self.doc.from_doctype and to_table_name == self.doc.to_doctype:
# Check validation
nm = sql("select name from `tab%s` where name = '%s' and %s" % (from_doctype, from_docname, validation_logic))
nm = nm and nm[0][0] or ''
# If validation failed raise exception
if not nm:
msgprint("Validation failed in doctype mapper. Please contact Administrator.")
raise Exception
from_doc = Document(from_doctype, nm)
# Maps field in parent
self.set_value(fld_list, from_doc, to_doc)
# Map custom fields
self.map_custom_fields(from_doctype, to_doctype, from_doc, to_doc)

# Parent to child OR child to child mapping
else:
dnlist = ()
if from_table_name == self.doc.from_doctype:
dnlist = ((from_docname,),)
else:
dnlist = sql("select name from `tab%s` where parent='%s' and parenttype = '%s' and %s order by idx" % (from_table_name, from_docname, self.doc.from_doctype, validation_logic))
for dn in dnlist:
# Add a row in target table in 'To DocType' and returns obj
ch = addchild(to_doc, t[3], t[1], 1, doclist)
# Creates object for 'From DocType', it can be parent or child
d = Document(t[0], dn[0])
# Map values
self.set_value(fld_list, d, ch)
# Map custom fields
self.map_custom_fields(from_table_name, t[1], d, ch)

# Required when called from server side for refreshing table
return doclist
# Assigns value to "To Doctype"
#------------------------------
def set_value(self, fld_list, obj, to_doc):
for f in fld_list:
if f[0].startswith('eval:'):
to_doc.fields[f[1]] = eval(f[0][5:])
else:
to_doc.fields[f[1]] = obj.fields.get(f[0])
# Validate
#---------
def validate(self):
for d in getlist(self.doclist, 'field_mapper_details'):
# Automatically assigns default value if not entered
if not d.match_id:
d.match_id = 0
if not d.map:
d.map = 'Yes'
for d in getlist(self.doclist, 'table_mapper_details'):
if not d.reference_doctype_key:
d.reference_doctype_key = ''
if not d.reference_key:
d.reference_key = ''
# Check wrong field name
self.check_fields_in_dt()

# Check if any wrong fieldname entered
#--------------------------------------
def check_fields_in_dt(self):
for d in getlist(self.doclist, 'field_mapper_details'):
table_name = sql("select from_table, to_table from `tabTable Mapper Detail` where parent ='%s' and match_id = '%s'" % (self.doc.name, d.match_id))
if table_name:
exists1 = sql("select name from tabDocField where parent = '%s' and fieldname = '%s'" % (table_name[0][0], d.from_field))
exists2 = sql("select name from tabDocField where parent = '%s' and fieldname = '%s'" % (table_name[0][1], d.to_field))
# Default fields like name, parent, owner does not exists in DocField
if not exists1 and d.from_field not in default_fields:
msgprint('"' + cstr(d.from_field) + '" does not exists in DocType "' + cstr(table_name[0][0]) + '"')
if not exists2 and d.to_field not in default_fields:
msgprint('"' + cstr(d.to_field) + '" does not exists in DocType "' + cstr(table_name[0][1]) + '"')
# Check consistency of value with reference document
#---------------------------------------------------
def validate_reference_value(self, obj, to_docname):
for t in getlist(self.doclist, 'table_mapper_details'):
# Reference key is the fieldname which will relate to the from_table
if t.reference_doctype_key:
for d in getlist(obj.doclist, t.to_field):
if d.fields[t.reference_doctype_key] == self.doc.from_doctype:
self.check_consistency(obj.doc, d, to_docname)
self.check_ref_docstatus()
# Make list of fields whose value will be consistent with prevdoc
#-----------------------------------------------------------------
def get_checklist(self):
checklist = []
for f in getlist(self.doclist, 'field_mapper_details'):
# Check which field's value will be compared
if f.checking_operator:
checklist.append([f.from_field, f.to_field, f.checking_operator, f.match_id])
return checklist
def check_fld_type(self, tbl, fld, cur_val):
ft = sql("select fieldtype from tabDocField where fieldname = '%s' and parent = '%s'" % (fld,tbl))
ft = ft and ft[0][0] or ''
if ft == 'Currency' or ft == 'Float':
cur_val = '%.2f' % cur_val
return cur_val, ft
# Check consistency
#-------------------
def check_consistency(self, par_obj, child_obj, to_docname):
checklist = self.get_checklist()
self.ref_doc = ''
for t in getlist(self.doclist, 'table_mapper_details'):
if t.reference_key and child_obj.fields[t.reference_key]:
for cl in checklist:
if cl[3] == t.match_id:
if t.to_field:
cur_val = child_obj.fields[cl[1]]
else:
cur_val = par_obj.fields[cl[1]]
ft = self.check_fld_type(t.to_table, cl[1], cur_val)
cur_val = ft[0]

if cl[2] == '=' and (ft[1] == 'Currency' or ft[1] == 'Float'):
consistent = sql("select name, %s from `tab%s` where name = '%s' and '%s' - %s <= 0.5" % (cl[0], t.from_table, child_obj.fields[t.reference_key], flt(cur_val), cl[0]))
else:
#consistent = sql("select name, %s from `tab%s` where name = '%s' and '%s' %s %s" % (cl[0], t.from_table, child_obj.fields[t.reference_key], cur_val, cl[2], cl[0]))
consistent = sql("select name, %s from `tab%s` where name = '%s' and '%s' %s ifnull(%s, '')" % (cl[0], t.from_table, child_obj.fields[t.reference_key], ft[1] in ('Currency', 'Float', 'Int') and flt(cur_val) or cstr(cur_val), cl[2], cl[0]))

if not self.ref_doc:
det = sql("select name, parent from `tab%s` where name = '%s'" % (t.from_table, child_obj.fields[t.reference_key]))
self.ref_doc = det[0][1] and det[0][1] or det[0][0]

if not consistent:
self.give_message(t.from_table, t.to_table, cl[0], cl[1], child_obj.fields[t.reference_key], cl[2])
# Gives message and raise exception
#-----------------------------------
def give_message(self, from_table, to_table, from_field, to_field, ref_value, operator):
# Select label of the field
to_fld_label = sql("select label from tabDocField where parent = '%s' and fieldname = '%s'" % (to_table, to_field))
from_fld_label = sql("select label from tabDocField where parent = '%s' and fieldname = '%s'" % (from_table, from_field))
op_in_words = {'=':'equal to ', '>=':'greater than equal to ', '>':'greater than ', '<=':'less than equal to ', '<':'less than '}
msgprint(to_fld_label[0][0] + " should be " + op_in_words[operator] + from_fld_label[0][0] + " of " + self.doc.from_doctype + ": " + self.ref_doc)
raise Exception, "Validation Error."
def check_ref_docstatus(self):
if self.ref_doc:
det = sql("select name, docstatus from `tab%s` where name = '%s'" % (self.doc.from_doctype, self.ref_doc))
if not det:
msgprint(self.doc.from_doctype + ": " + self.ref_doc + " does not exists in the system")
raise Exception, "Validation Error."
elif self.doc.ref_doc_submitted and det[0][1] != 1:
msgprint(self.doc.from_doctype + ": " + self.ref_doc + " is not Submitted Document.")
raise Exception, "Validation Error."

def on_update(self):
import webnotes.defs
if hasattr(webnotes.defs, 'developer_mode') and webnotes.defs.developer_mode:
from webnotes.modules.export_module import export_to_files
export_to_files(record_list=[[self.doc.doctype, self.doc.name]])
def __init__(self, doc, doclist=[]):
self.doc = doc
self.doclist = doclist
self.prefix = is_testing and 'test' or 'tab'
self.ref_doc = ''
# Autoname
#---------
def autoname(self):
self.doc.name = make_autoname(self.doc.from_doctype + '-' + self.doc.to_doctype)

def map_fields_with_same_name(self, from_doctype, to_doctype, from_doc, to_doc, fld_list):
"""
Returns field list with same name in from and to doctype
"""
exception_flds = [f[0] for f in fld_list if f[2] == 'No']
exception_flds += default_fields
exception_flds += ['amended_from', 'amendment_date', 'file_list', 'naming_series', 'status']
map_fld_list = [
[d[0], d[0], 'Yes'] for d in sql("""
select t1.fieldname
from `tabDocField` t1, `tabDocField` t2
where t1.parent = %s and t2.parent = %s
and t1.fieldname = t2.fieldname
and t1.docstatus != 2 and t2.docstatus != 2
and ifnull(t1.fieldname, '') != ''
""",(from_doctype, to_doctype)) if d[0] not in exception_flds
]

self.set_value(map_fld_list, from_doc, to_doc)
# Maps the fields in 'To DocType'
#--------------------------------
def dt_map(self, from_doctype, to_doctype, from_docname, to_doc, doclist, from_to_list = '[]'):

# definition of arguments
'''
String <from_doctype> : contains the name of DocType initiating the function
String <to_doctype> : contains the name of DocType created by the function
String <from_docname> : contains ID(name) of 'from_doctype'
String <to_doc> : contains doc of 'to_doctype'
String <doclist> : contains doclist of 'to_doctype'
String <from_to_list> : contains list of tables which will be mapped
'''
# Validate reference doc docstatus
self.ref_doc = from_docname
self.check_ref_docstatus()
if not doclist:
doclist.append(to_doc)

tbl_list = sql("select from_table, to_table, from_field, to_field, match_id, validation_logic from `tabTable Mapper Detail` where parent ='%s' order by match_id" % (from_doctype + "-" + to_doctype))

for t in tbl_list:
from_table_name = t[0]
to_table_name = t[1]
from_table_fname = t[2]
to_table_fname = t[3]
match_id = t[4]
validation_logic = t[5]

from_to = [from_table_name, to_table_name]

if from_to in eval(from_to_list):
fld_list = sql("select from_field, to_field, map from `tabField Mapper Detail` where parent = '%s' and match_id = %s" % (from_doctype + "-" + to_doctype, match_id))
if not from_docname:
msgprint(from_doctype + " not selected for mapping")
raise Exception
# Parent to parent mapping
if from_table_name == self.doc.from_doctype and to_table_name == self.doc.to_doctype:
# Check validation
nm = sql("select name from `tab%s` where name = '%s' and %s" % (from_doctype, from_docname, validation_logic))
nm = nm and nm[0][0] or ''
# If validation failed raise exception
if not nm:
msgprint("Validation failed in doctype mapper. Please contact Administrator.")
raise Exception
from_doc = Document(from_doctype, nm)

# Map fields with same name

self.map_fields_with_same_name(from_doctype, to_doctype, from_doc, to_doc, fld_list)
# Maps field in parent
if fld_list:
self.set_value(fld_list, from_doc, to_doc)


# Parent to child OR child to child mapping
else:
dnlist = ()
if from_table_name == self.doc.from_doctype:
dnlist = ((from_docname,),)
else:
dnlist = sql("select name from `tab%s` where parent='%s' and parenttype = '%s' and %s order by idx" % (from_table_name, from_docname, self.doc.from_doctype, validation_logic))
for dn in dnlist:
# Add a row in target table in 'To DocType' and returns obj
ch = addchild(to_doc, t[3], t[1], 1, doclist)
# Creates object for 'From DocType', it can be parent or child
d = Document(t[0], dn[0])
# Map fields with same name
self.map_fields_with_same_name(from_table_name, t[1], d, ch, fld_list)
# Map values
if fld_list:
self.set_value(fld_list, d, ch)



# Required when called from server side for refreshing table
return doclist
# Assigns value to "To Doctype"
#------------------------------
def set_value(self, fld_list, obj, to_doc):
for f in fld_list:
if f[2] == 'Yes':
if f[0].startswith('eval:'):
to_doc.fields[f[1]] = eval(f[0][5:])
else:
to_doc.fields[f[1]] = obj.fields.get(f[0])
# Validate
#---------
def validate(self):
for d in getlist(self.doclist, 'field_mapper_details'):
# Automatically assigns default value if not entered
if not d.match_id:
d.match_id = 0
if not d.map:
d.map = 'Yes'
for d in getlist(self.doclist, 'table_mapper_details'):
if not d.reference_doctype_key:
d.reference_doctype_key = ''
if not d.reference_key:
d.reference_key = ''
# Check wrong field name
self.check_fields_in_dt()

# Check if any wrong fieldname entered
#--------------------------------------
def check_fields_in_dt(self):
for d in getlist(self.doclist, 'field_mapper_details'):
table_name = sql("select from_table, to_table from `tabTable Mapper Detail` where parent ='%s' and match_id = '%s'" % (self.doc.name, d.match_id))
if table_name:
exists1 = sql("select name from tabDocField where parent = '%s' and fieldname = '%s'" % (table_name[0][0], d.from_field))
exists2 = sql("select name from tabDocField where parent = '%s' and fieldname = '%s'" % (table_name[0][1], d.to_field))
# Default fields like name, parent, owner does not exists in DocField
if not exists1 and d.from_field not in default_fields:
msgprint('"' + cstr(d.from_field) + '" does not exists in DocType "' + cstr(table_name[0][0]) + '"')
if not exists2 and d.to_field not in default_fields:
msgprint('"' + cstr(d.to_field) + '" does not exists in DocType "' + cstr(table_name[0][1]) + '"')
# Check consistency of value with reference document
#---------------------------------------------------
def validate_reference_value(self, obj, to_docname):
for t in getlist(self.doclist, 'table_mapper_details'):
# Reference key is the fieldname which will relate to the from_table
if t.reference_doctype_key:
for d in getlist(obj.doclist, t.to_field):
if d.fields[t.reference_doctype_key] == self.doc.from_doctype:
self.check_consistency(obj.doc, d, to_docname)
self.check_ref_docstatus()
# Make list of fields whose value will be consistent with prevdoc
#-----------------------------------------------------------------
def get_checklist(self):
checklist = []
for f in getlist(self.doclist, 'field_mapper_details'):
# Check which field's value will be compared
if f.checking_operator:
checklist.append([f.from_field, f.to_field, f.checking_operator, f.match_id])
return checklist
def check_fld_type(self, tbl, fld, cur_val):
ft = sql("select fieldtype from tabDocField where fieldname = '%s' and parent = '%s'" % (fld,tbl))
ft = ft and ft[0][0] or ''
if ft == 'Currency' or ft == 'Float':
cur_val = '%.2f' % cur_val
return cur_val, ft
# Check consistency
#-------------------
def check_consistency(self, par_obj, child_obj, to_docname):
checklist = self.get_checklist()
self.ref_doc = ''
for t in getlist(self.doclist, 'table_mapper_details'):
if t.reference_key and child_obj.fields[t.reference_key]:
for cl in checklist:
if cl[3] == t.match_id:
if t.to_field:
cur_val = child_obj.fields[cl[1]]
else:
cur_val = par_obj.fields[cl[1]]
ft = self.check_fld_type(t.to_table, cl[1], cur_val)
cur_val = ft[0]

if cl[2] == '=' and (ft[1] == 'Currency' or ft[1] == 'Float'):
consistent = sql("select name, %s from `tab%s` where name = '%s' and '%s' - %s <= 0.5" % (cl[0], t.from_table, child_obj.fields[t.reference_key], flt(cur_val), cl[0]))
else:
#consistent = sql("select name, %s from `tab%s` where name = '%s' and '%s' %s %s" % (cl[0], t.from_table, child_obj.fields[t.reference_key], cur_val, cl[2], cl[0]))
consistent = sql("select name, %s from `tab%s` where name = '%s' and '%s' %s ifnull(%s, '')" % (cl[0], t.from_table, child_obj.fields[t.reference_key], ft[1] in ('Currency', 'Float', 'Int') and flt(cur_val) or cstr(cur_val), cl[2], cl[0]))

if not self.ref_doc:
det = sql("select name, parent from `tab%s` where name = '%s'" % (t.from_table, child_obj.fields[t.reference_key]))
self.ref_doc = det[0][1] and det[0][1] or det[0][0]

if not consistent:
self.give_message(t.from_table, t.to_table, cl[0], cl[1], child_obj.fields[t.reference_key], cl[2])
# Gives message and raise exception
#-----------------------------------
def give_message(self, from_table, to_table, from_field, to_field, ref_value, operator):
# Select label of the field
to_fld_label = sql("select label from tabDocField where parent = '%s' and fieldname = '%s'" % (to_table, to_field))
from_fld_label = sql("select label from tabDocField where parent = '%s' and fieldname = '%s'" % (from_table, from_field))
op_in_words = {'=':'equal to ', '>=':'greater than equal to ', '>':'greater than ', '<=':'less than equal to ', '<':'less than '}
msgprint(to_fld_label[0][0] + " should be " + op_in_words[operator] + from_fld_label[0][0] + " of " + self.doc.from_doctype + ": " + self.ref_doc)
raise Exception, "Validation Error."
def check_ref_docstatus(self):
if self.ref_doc:
det = sql("select name, docstatus from `tab%s` where name = '%s'" % (self.doc.from_doctype, self.ref_doc))
if not det:
msgprint(self.doc.from_doctype + ": " + self.ref_doc + " does not exists in the system")
raise Exception, "Validation Error."
elif self.doc.ref_doc_submitted and det[0][1] != 1:
msgprint(self.doc.from_doctype + ": " + self.ref_doc + " is not Submitted Document.")
raise Exception, "Validation Error."

def on_update(self):
import webnotes.defs
if hasattr(webnotes.defs, 'developer_mode') and webnotes.defs.developer_mode:
from webnotes.modules.export_module import export_to_files
export_to_files(record_list=[[self.doc.doctype, self.doc.name]])

+ 9
- 0
cgi-bin/core/doctype/event/event.js Näytä tiedosto

@@ -0,0 +1,9 @@
cur_frm.cscript.onload = function(doc, cdt, cdn) {
var df = get_field('Event', 'Intro HTML', doc.name);
if(doc.ref_type) {
ref = repl(cur_frm.cstring.ref_html, {'dt': doc.ref_type, 'dn':doc.ref_name});
} else var ref = '';
df.options = repl(cur_frm.cstring.intro_html, {'ref': ref});
refresh_fields('Intro HTML');
}

+ 14
- 0
cgi-bin/core/doctype/file/file.py Näytä tiedosto

@@ -0,0 +1,14 @@
class DocType:
def __init__(self, d, dl):
self.doc, self.doclist = d,dl

def validate(self):
# check for extension
if not '.' in self.doc.file_name:
msgprint("Extension required in file name")
raise Exception

# set mime type
if not self.doc.mime_type:
import mimetypes
self.doc.mime_type = mimetypes.guess_type(self.doc.file_name)[0] or 'application/unknown'

+ 103
- 423
cgi-bin/core/doctype/profile/profile.txt Näytä tiedosto

@@ -5,25 +5,22 @@
{
'creation': '2009-05-12 11:19:11',
'docstatus': 0,
'modified': '2010-12-21 11:07:20',
'modified_by': 'sneha@webnotestech.com',
'modified': '2011-08-25 14:02:26',
'modified_by': 'Administrator',
'owner': 'Administrator'
},

# These values are common for all DocType
{
'_last_update': '1303708853',
'_last_update': '1311340897',
'allow_attach': 1,
'allow_copy': 0,
'allow_email': 0,
'allow_print': 0,
'client_script': 'cur_frm.cscript[\'Change Password\']= function(doc, cdt, cdn) {\n var error = false;\n if ((!doc.new_password)||(!doc.retype_new_password)){\n alert("Both fields are required!");\n error = true;\n }\n if (doc.new_password.length<4) {\n alert("Password must be atleast 4 characters long");\n error = true;\n }\n if(doc.new_password!=doc.retype_new_password) {\n alert("Passwords must match");\n error = true;\n }\n if(!/[A-Z]/.test(doc.new_password) || !/[0-9]/.test(doc.new_password) || !/[\\W_]/.test(doc.new_password)) {\n msgprint(\'New password must contain atleast 1 capital letter, 1 numeric and 1 special character.\');\n error = true;\n doc.new_password = \'\';\n refresh_field(\'new_password\');\n }\n if(!error) {\n cur_frm.runscript(\'update_password\', \'\', function(r,t) {\n\tdoc.new_password = \'\';\n\tdoc.retype_new_password = \'\';\n refresh_many([\'new_password\',\'retype_new_password\']);\n });\n }\n}\n\ncur_frm.cscript.validate = function(doc, cdt, cdn) {\n doc.new_password = \'\';\n doc.retype_new_password = \'\';\n}',
'colour': 'White:FFF',
'doctype': 'DocType',
'hide_heading': 0,
'hide_toolbar': 0,
'idx': 0,
'in_create': 1,
'issingle': 0,
'istable': 0,
'max_attachments': 1,
@@ -31,10 +28,9 @@
'name': '__common__',
'print_outline': 'Yes',
'read_only': 0,
'section_style': 'Tray',
'server_code_error': ' ',
'search_fields': 'first_name, last_name',
'show_in_menu': 0,
'version': 25
'version': 32
},

# These values are common for all DocField
@@ -69,7 +65,6 @@
'create': 1,
'doctype': 'DocPerm',
'execute': 0,
'idx': 1,
'permlevel': 0,
'role': 'Administrator',
'submit': 0
@@ -79,7 +74,6 @@
{
'create': 1,
'doctype': 'DocPerm',
'idx': 2,
'permlevel': 0,
'role': 'System Manager'
},
@@ -87,7 +81,6 @@
# DocPerm
{
'doctype': 'DocPerm',
'idx': 3,
'permlevel': 1,
'role': 'Administrator'
},
@@ -95,7 +88,6 @@
# DocPerm
{
'doctype': 'DocPerm',
'idx': 4,
'match': 'owner',
'permlevel': 0,
'role': 'All'
@@ -103,85 +95,52 @@

# DocField
{
'default': '1',
'doctype': 'DocField',
'fieldtype': 'Section Break',
'hidden': 0,
'idx': 1,
'label': 'Details',
'oldfieldtype': 'Section Break',
'permlevel': 0,
'reqd': 0,
'search_index': 0
},

# DocField
{
'doctype': 'DocField',
'fieldtype': 'Column Break',
'hidden': 0,
'idx': 2,
'label': 'Picture',
'oldfieldtype': 'Column Break',
'permlevel': 0,
'reqd': 0,
'search_index': 0,
'width': '50%'
},

# DocField
{
'doctype': 'DocField',
'fieldtype': 'Image',
'idx': 3,
'label': 'Profile Picture',
'oldfieldtype': 'Image',
'permlevel': 0
'fieldname': 'enabled',
'fieldtype': 'Check',
'label': 'Enabled',
'oldfieldname': 'enabled',
'oldfieldtype': 'Check',
'permlevel': 1
},

# DocField
{
'doctype': 'DocField',
'fieldtype': 'Column Break',
'idx': 4,
'label': 'Contact',
'oldfieldtype': 'Column Break',
'permlevel': 0,
'width': '50%'
'fieldname': 'password',
'fieldtype': 'Password',
'label': 'Password',
'permlevel': 1,
'hidden': 1
},
# DocField
{
'default': '1',
'doctype': 'DocField',
'fieldname': 'enabled',
'fieldname': 'registered',
'fieldtype': 'Check',
'idx': 5,
'label': 'Enabled',
'oldfieldname': 'enabled',
'oldfieldtype': 'Check',
'permlevel': 1
'label': 'Registered',
'permlevel': 0,
'hidden': 1
},

# DocField
{
'default': '1',
'doctype': 'DocField',
'fieldname': 'send_email_invite',
'fieldname': 'unsubscribed',
'fieldtype': 'Check',
'idx': 6,
'label': 'Send Email Invite',
'oldfieldname': 'send_email_invite',
'oldfieldtype': 'Check',
'permlevel': 1
'label': 'Unsubscribed',
'permlevel': 0,
'hidden': 1
},
# DocField
{
'doctype': 'DocField',
'fieldname': 'recent_documents',
'fieldtype': 'Text',
'hidden': 1,
'idx': 8,
'label': 'Recent Documents',
'oldfieldname': 'recent_documents',
'oldfieldtype': 'Text',
@@ -195,7 +154,6 @@
'doctype': 'DocField',
'fieldname': 'first_name',
'fieldtype': 'Data',
'idx': 9,
'label': 'First Name',
'oldfieldname': 'first_name',
'oldfieldtype': 'Data',
@@ -208,7 +166,6 @@
'doctype': 'DocField',
'fieldname': 'middle_name',
'fieldtype': 'Data',
'idx': 10,
'label': 'Middle Name (Optional)',
'oldfieldname': 'middle_name',
'oldfieldtype': 'Data',
@@ -220,46 +177,17 @@
'doctype': 'DocField',
'fieldname': 'last_name',
'fieldtype': 'Data',
'idx': 11,
'label': 'Last Name',
'oldfieldname': 'last_name',
'oldfieldtype': 'Data',
'permlevel': 0
},

# DocField
{
'doctype': 'DocField',
'fieldname': 'email',
'fieldtype': 'Data',
'hidden': 0,
'idx': 12,
'label': 'Email',
'oldfieldname': 'email',
'oldfieldtype': 'Data',
'permlevel': 0,
'reqd': 1,
'search_index': 0
},

# DocField
{
'doctype': 'DocField',
'fieldname': 'birth_date',
'fieldtype': 'Date',
'idx': 13,
'label': 'Birth Date',
'oldfieldname': 'birth_date',
'oldfieldtype': 'Date',
'permlevel': 0
},

# DocField
{
'doctype': 'DocField',
'fieldname': 'gender',
'fieldtype': 'Select',
'idx': 14,
'label': 'Gender',
'oldfieldname': 'gender',
'oldfieldtype': 'Select',
@@ -271,51 +199,74 @@
# DocField
{
'doctype': 'DocField',
'fieldname': 'occupation',
'fieldtype': 'Column Break',
'oldfieldtype': 'Column Break',
'permlevel': 1,
'width': '50%'
},

# DocField
{
'doctype': 'DocField',
'fieldname': 'email',
'fieldtype': 'Data',
'idx': 15,
'label': 'Designation',
'oldfieldname': 'occupation',
'hidden': 0,
'label': 'Email',
'oldfieldname': 'email',
'oldfieldtype': 'Data',
'permlevel': 0,
'reqd': 1,
'search_index': 0
},

# DocField
{
'doctype': 'DocField',
'fieldname': 'bio',
'fieldtype': 'Text',
'idx': 16,
'label': 'Bio',
'oldfieldname': 'bio',
'oldfieldtype': 'Text',
'permlevel': 0,
'search_index': 0
'search_index': 0,
'hidden': 1
},


# DocField
{
'doctype': 'DocField',
'fieldname': 'interests',
'fieldtype': 'Text',
'idx': 17,
'label': 'Interests',
'oldfieldname': 'interests',
'oldfieldtype': 'Text',
'permlevel': 0,
'hidden': 1
},

# DocField
{
'doctype': 'DocField',
'fieldname': 'birth_date',
'fieldtype': 'Date',
'label': 'Birth Date',
'oldfieldname': 'birth_date',
'oldfieldtype': 'Date',
'permlevel': 0
},


# DocField
{
'doctype': 'DocField',
'fieldname': 'activities',
'fieldtype': 'Text',
'idx': 18,
'label': 'Activities',
'oldfieldname': 'activities',
'oldfieldtype': 'Text',
'permlevel': 0
'permlevel': 0,
'hidden': 1
},

# DocField
@@ -323,7 +274,6 @@
'doctype': 'DocField',
'fieldname': 'messanger_status',
'fieldtype': 'Data',
'idx': 19,
'label': 'Messanger Status',
'oldfieldname': 'messanger_status',
'oldfieldtype': 'Data',
@@ -331,60 +281,11 @@
'search_index': 0
},

# DocField
{
'doctype': 'DocField',
'fieldname': 'home_phone',
'fieldtype': 'Data',
'idx': 20,
'label': 'Home Phone',
'oldfieldname': 'home_phone',
'oldfieldtype': 'Data',
'permlevel': 0
},

# DocField
{
'doctype': 'DocField',
'fieldname': 'office_phone',
'fieldtype': 'Data',
'idx': 21,
'label': 'Office Phone',
'oldfieldname': 'office_phone',
'oldfieldtype': 'Data',
'permlevel': 0
},

# DocField
{
'doctype': 'DocField',
'fieldname': 'extension',
'fieldtype': 'Data',
'idx': 22,
'label': 'Extension',
'oldfieldname': 'extension',
'oldfieldtype': 'Data',
'permlevel': 0
},

# DocField
{
'doctype': 'DocField',
'fieldname': 'cell_no',
'fieldtype': 'Data',
'idx': 23,
'label': 'Cell No',
'oldfieldname': 'cell_no',
'oldfieldtype': 'Data',
'permlevel': 0
},

# DocField
{
'doctype': 'DocField',
'fieldname': 'user_type',
'fieldtype': 'Select',
'idx': 24,
'label': 'User Type',
'oldfieldname': 'user_type',
'oldfieldtype': 'Select',
@@ -392,150 +293,27 @@
'permlevel': 0
},

# DocField
{
'doctype': 'DocField',
'fieldname': 'last_login',
'fieldtype': 'Read Only',
'hidden': 0,
'idx': 25,
'label': 'Last Login',
'oldfieldname': 'last_login',
'oldfieldtype': 'Read Only',
'permlevel': 0,
'reqd': 0,
'search_index': 0
},

# DocField
{
'doctype': 'DocField',
'fieldname': 'last_ip',
'fieldtype': 'Read Only',
'idx': 26,
'label': 'Last IP',
'oldfieldname': 'last_ip',
'oldfieldtype': 'Read Only',
'permlevel': 0
},

# DocField
{
'doctype': 'DocField',
'fieldtype': 'Section Break',
'idx': 27,
'label': 'Address',
'oldfieldtype': 'Section Break',
'permlevel': 0
},

# DocField
{
'doctype': 'DocField',
'fieldname': 'line_1',
'fieldtype': 'Data',
'idx': 28,
'label': 'Line 1',
'oldfieldname': 'line_1',
'oldfieldtype': 'Data',
'permlevel': 0
},

# DocField
{
'doctype': 'DocField',
'fieldname': 'line_2',
'fieldtype': 'Data',
'idx': 29,
'label': 'Line 2',
'oldfieldname': 'line_2',
'oldfieldtype': 'Data',
'permlevel': 0
},

# DocField
{
'doctype': 'DocField',
'fieldname': 'city',
'fieldtype': 'Data',
'idx': 30,
'label': 'City / Town',
'oldfieldname': 'city',
'oldfieldtype': 'Data',
'permlevel': 0,
'reqd': 0
},

# DocField
{
'doctype': 'DocField',
'fieldname': 'district',
'fieldtype': 'Data',
'idx': 31,
'label': 'District',
'oldfieldname': 'district',
'oldfieldtype': 'Data',
'permlevel': 0
},

# DocField
{
'doctype': 'DocField',
'fieldname': 'state',
'fieldtype': 'Data',
'idx': 32,
'label': 'State',
'oldfieldname': 'state',
'oldfieldtype': 'Data',
'permlevel': 0
},

# DocField
{
'doctype': 'DocField',
'fieldname': 'country',
'fieldtype': 'Data',
'idx': 33,
'label': 'Country',
'oldfieldname': 'country',
'oldfieldtype': 'Data',
'permlevel': 0
},

# DocField
{
'doctype': 'DocField',
'fieldname': 'pin',
'fieldtype': 'Data',
'idx': 34,
'label': 'Pin',
'oldfieldname': 'pin',
'oldfieldtype': 'Data',
'permlevel': 0
},

# DocField
{
'doctype': 'DocField',
'fieldtype': 'Section Break',
'idx': 35,
'label': 'User Role',
'hidden': 0,
'oldfieldtype': 'Section Break',
'permlevel': 1
'permlevel': 1,
'reqd': 0,
'search_index': 0
},

# DocField
{
'doctype': 'DocField',
'fieldtype': 'Section Break',
'hidden': 0,
'idx': 36,
'fieldtype': 'Column Break',
'label': 'Roles',
'oldfieldtype': 'Section Break',
'oldfieldtype': 'Column Break',
'permlevel': 1,
'reqd': 0,
'search_index': 0
},
'width': '50%'
},

# DocField
{
@@ -545,7 +323,6 @@
'fieldname': 'userroles',
'fieldtype': 'Table',
'hidden': 0,
'idx': 37,
'label': 'User Roles',
'oldfieldname': 'userroles',
'oldfieldtype': 'Table',
@@ -558,10 +335,9 @@
# DocField
{
'doctype': 'DocField',
'fieldtype': 'Section Break',
'idx': 38,
'fieldtype': 'Column Break',
'label': 'System Defaults',
'oldfieldtype': 'Section Break',
'oldfieldtype': 'Column Break',
'permlevel': 1,
'width': '50%'
},
@@ -574,7 +350,6 @@
'fieldname': 'defaults',
'fieldtype': 'Table',
'hidden': 0,
'idx': 39,
'label': 'Defaults',
'oldfieldname': 'defaults',
'oldfieldtype': 'Table',
@@ -588,145 +363,69 @@
{
'doctype': 'DocField',
'fieldtype': 'Section Break',
'idx': 40,
'label': 'Password',
'label': 'Login Details',
'oldfieldtype': 'Section Break',
'permlevel': 0
},

# DocField
{
'doctype': 'DocField',
'fieldtype': 'Column Break',
'idx': 41,
'label': 'Change Your Password',
'oldfieldtype': 'Column Break',
'permlevel': 1,
'width': '50%'
},

# DocField
{
'colour': 'Pink:FEF2EA',
'doctype': 'DocField',
'fieldname': 'password',
'fieldtype': 'Data',
'hidden': 1,
'idx': 42,
'label': 'Current Password',
'oldfieldname': 'password',
'oldfieldtype': 'Data',
'permlevel': 1,
'reqd': 0,
'search_index': 0
},

# DocField
{
'doctype': 'DocField',
'fieldname': 'new_password',
'fieldtype': 'Password',
'idx': 43,
'label': 'New Password',
'oldfieldname': 'new_password',
'oldfieldtype': 'Password',
'permlevel': 1
},

# DocField
{
'doctype': 'DocField',
'fieldname': 'retype_new_password',
'fieldtype': 'Password',
'idx': 44,
'label': 'Retype New Password',
'oldfieldname': 'retype_new_password',
'oldfieldtype': 'Password',
'permlevel': 1
},

# DocField
{
'doctype': 'DocField',
'fieldname': 'password_last_updated',
'fieldtype': 'Date',
'hidden': 1,
'idx': 45,
'label': 'Password Last Updated',
'oldfieldname': 'password_last_updated',
'oldfieldtype': 'Date',
'permlevel': 1,
'print_hide': 1
'permlevel': 0,
},

# DocField
{
'doctype': 'DocField',
'fieldtype': 'Button',
'idx': 46,
'label': 'Change Password',
'oldfieldtype': 'Button',
'permlevel': 1,
'trigger': 'Client',
'width': '120px'
'fieldname': 'login_before',
'fieldtype': 'Int',
'label': 'Login Before',
'permlevel': 0
},

# DocField
{
'doctype': 'DocField',
'fieldtype': 'Section Break',
'idx': 47,
'label': 'Attachment',
'oldfieldtype': 'Section Break',
'permlevel': 1
'fieldname': 'login_after',
'fieldtype': 'Int',
'label': 'Login After',
'permlevel': 0
},

# DocField
{
'default': '0',
'doctype': 'DocField',
'fieldname': 'social_points',
'fieldtype': 'Int',
'idx': 48,
'label': 'Social Points',
'oldfieldname': 'social_points',
'oldfieldtype': 'Int',
'fieldname': 'restrict_ip',
'fieldtype': 'Data',
'label': 'Restrict IP',
'permlevel': 0
},

# DocField
{
'doctype': 'DocField',
'fieldname': 'social_badge',
'fieldtype': 'Data',
'idx': 49,
'label': 'Social Badge',
'oldfieldname': 'social_badge',
'oldfieldtype': 'Data',
'permlevel': 0
'fieldtype': 'Column Break',
'oldfieldtype': 'Column Break',
'width': '50%'
},

# DocField
{
'doctype': 'DocField',
'fieldname': 'avatar',
'fieldtype': 'Data',
'idx': 50,
'label': 'Avatar',
'oldfieldname': 'avatar',
'oldfieldtype': 'Data',
'permlevel': 0
'fieldname': 'last_login',
'fieldtype': 'Read Only',
'hidden': 0,
'label': 'Last Login',
'oldfieldname': 'last_login',
'oldfieldtype': 'Read Only',
'permlevel': 0,
'reqd': 0,
'search_index': 0
},

# DocField
{
'doctype': 'DocField',
'fieldtype': 'HTML',
'idx': 51,
'label': 'Attachment HTML',
'oldfieldtype': 'HTML',
'options': 'First attachment must be the picture',
'permlevel': 1
'fieldname': 'last_ip',
'fieldtype': 'Read Only',
'label': 'Last IP',
'oldfieldname': 'last_ip',
'oldfieldtype': 'Read Only',
'permlevel': 0
},

# DocField
@@ -735,28 +434,9 @@
'fieldname': 'file_list',
'fieldtype': 'Text',
'hidden': 1,
'idx': 52,
'label': 'File List',
'oldfieldname': 'file_list',
'oldfieldtype': 'Text',
'permlevel': 0
},

# DocField
{
'doctype': 'DocField',
'fieldname': 'fiscal_year',
'fieldtype': 'Select',
'hidden': 1,
'idx': 53,
'in_filter': 1,
'label': 'Fiscal Year',
'no_copy': 1,
'oldfieldname': 'fiscal_year',
'oldfieldtype': 'Select',
'options': 'link:Fiscal Year',
'permlevel': 0,
'print_hide': 1,
'report_hide': 1
}
}
]

+ 8
- 66
cgi-bin/core/doctype/search_criteria/search_criteria.txt Näytä tiedosto

@@ -87,10 +87,13 @@
# DocField
{
'doctype': 'DocField',
'fieldtype': 'Section Break',
'idx': 1,
'label': 'Details',
'oldfieldtype': 'Section Break',
'fieldname': 'criteria_name',
'fieldtype': 'Data',
'hidden': 0,
'idx': 5,
'label': 'Criteria Name',
'oldfieldname': 'criteria_name',
'oldfieldtype': 'Data',
'permlevel': 0
},

@@ -135,41 +138,6 @@
'search_index': 1
},

# DocField
{
'doctype': 'DocField',
'fieldname': 'criteria_name',
'fieldtype': 'Data',
'hidden': 0,
'idx': 5,
'label': 'Criteria Name',
'oldfieldname': 'criteria_name',
'oldfieldtype': 'Data',
'permlevel': 0
},

# DocField
{
'doctype': 'DocField',
'fieldname': 'description',
'fieldtype': 'Text',
'idx': 6,
'label': 'Description',
'oldfieldname': 'description',
'oldfieldtype': 'Text',
'permlevel': 0,
'width': '300px'
},

# DocField
{
'doctype': 'DocField',
'fieldtype': 'Section Break',
'idx': 7,
'label': 'Query Details',
'oldfieldtype': 'Section Break',
'permlevel': 0
},

# DocField
{
@@ -189,7 +157,7 @@
'doctype': 'DocField',
'fieldname': 'filters',
'fieldtype': 'Text',
'hidden': 0,
'hidden': 1,
'idx': 9,
'label': 'Filters',
'oldfieldname': 'filters',
@@ -288,32 +256,6 @@
'permlevel': 0
},

# DocField
{
'doctype': 'DocField',
'fieldname': 'graph_series',
'fieldtype': 'Data',
'hidden': 0,
'idx': 17,
'label': 'Graph Series',
'oldfieldname': 'graph_series',
'oldfieldtype': 'Data',
'permlevel': 0
},

# DocField
{
'doctype': 'DocField',
'fieldname': 'graph_values',
'fieldtype': 'Data',
'hidden': 0,
'idx': 18,
'label': 'Graph Values',
'oldfieldname': 'graph_values',
'oldfieldtype': 'Data',
'permlevel': 0
},

# DocField
{
'doctype': 'DocField',


+ 3
- 1
cgi-bin/core/doctype/system_console/system_console.js Näytä tiedosto

@@ -1,10 +1,12 @@
cur_frm.cscript['Server (Python)'] = function(doc, dt, dn) {
doc.response = 'Executing...'
refresh_field('response');
$c_obj([doc], 'execute_server', '', function(r, rt) {
doc = locals[doc.doctype][doc.name];
if(r.exc) {
doc.response = r.exc;
} else {
doc.response = 'Worked!'
doc.response = 'Worked!'.bold()
}
refresh_field('response');
})


+ 14
- 1
cgi-bin/webnotes/__init__.py Näytä tiedosto

@@ -94,10 +94,13 @@ def errprint(msg):
"""
debug_log.append(cstr(msg or ''))

def msgprint(msg, small=0, raise_exception=0):
def msgprint(msg, small=0, raise_exception=0, as_table=False):
"""
Append to the :data:`message_log`
"""
if as_table and type(msg) in (list, tuple):
msg = '<table border="1px" style="border-collapse: collapse" cellpadding="2px">' + ''.join(['<tr>'+''.join(['<td>%s</td>' % c for c in r])+'</tr>' for r in msg]) + '</table>'
message_log.append((small and '__small:' or '')+cstr(msg or ''))
if raise_exception:
raise ValidationError
@@ -197,3 +200,13 @@ def setup_logging():
if getattr(defs, 'log_file_name', None):
setup_logging()
def get_db_password(db_name):
from webnotes import defs
if hasattr(defs, 'get_db_password'):
return defs.get_db_password(db_name)
elif hasattr(defs, 'db_password'):
return defs.db_password
else:
return db_name

+ 33
- 10
cgi-bin/webnotes/auth.py Näytä tiedosto

@@ -104,7 +104,7 @@ class HTTPRequest:
else:
db_name = getattr(webnotes.defs,'default_db_name','')
webnotes.conn = webnotes.db.Database(user = db_name,password = getattr(webnotes.defs,'db_password',''))
webnotes.conn = webnotes.db.Database(user = db_name,password = getattr(webnotes.defs,'db_password', ''))
webnotes.ac_name = ac_name

# =================================================================================
@@ -127,8 +127,9 @@ class LoginManager:
# ---------------------------
def post_login(self):
self.validate_ip_address()
self.run_trigger()
self.validate_ip_address()
self.validate_hour()
# check password
# --------------
@@ -186,16 +187,38 @@ class LoginManager:
# -------------
def validate_ip_address(self):
try:
ip = webnotes.conn.sql("select ip_address from tabProfile where name = '%s'" % self.user)[0][0] or ''
except: return
ip_list = webnotes.conn.get_value('Profile', self.user, 'restrict_ip', ignore=True)
if not ip_list:
return

ip_list = ip_list.replace(",", "\n").split('\n')
ip_list = [i.strip() for i in ip_list]

for ip in ip_list:
if webnotes.remote_ip.startswith(ip):
return
ip = ip.replace(",", "\n").split('\n')
ip = [i.strip() for i in ip]
webnotes.msgprint('Not allowed from this IP Address', raise_exception=1)

def validate_hour(self):
"""
check if user is logging in during restricted hours
"""
login_before = int(webnotes.conn.get_value('Profile', self.user, 'login_before', ignore=True) or 0)
login_after = int(webnotes.conn.get_value('Profile', self.user, 'login_after', ignore=True) or 0)
if not (login_before or login_after):
return
if ret and ip:
if not (webnotes.remote_ip.startswith(ip[0]) or (webnotes.remote_ip in ip)):
raise Exception, 'Not allowed from this IP Address'
from webnotes.utils import now_datetime
current_hour = int(now_datetime().strftime('%H'))
if login_before and current_hour > login_before:
webnotes.msgprint('Not allowed to login after restricted hour', raise_exception=1)

if login_after and current_hour < login_after:
webnotes.msgprint('Not allowed to login before restricted hour', raise_exception=1)

# login as guest
# --------------


+ 12
- 5
cgi-bin/webnotes/db.py Näytä tiedosto

@@ -26,7 +26,7 @@ class Database:
self.transaction_writes = 0
self.testing_tables = []

self.password = self.get_db_password(ac_name, password)
self.password = self.get_db_password(user, password)
self.connect()
if self.user != 'root':
@@ -57,7 +57,9 @@ class Database:
return ''
def get_db_login(self, ac_name):
return getattr(defs,'db_name_map').get(ac_name, getattr(defs,'default_db_name'))
if hasattr(defs, 'db_name_map'):
return getattr(defs,'db_name_map').get(ac_name, getattr(defs,'default_db_name'))
else: return ac_name

def connect(self):
"""
@@ -253,7 +255,7 @@ class Database:
# ======================================================================================
# get a single value from a record

def get_value(self, doctype, docname, fieldname):
def get_value(self, doctype, docname, fieldname, ignore=None):
"""
Get a single / multiple value from a record.

@@ -264,8 +266,13 @@ class Database:
if docname and (docname!=doctype or docname=='DocType'):
if type(fieldname) in (list, tuple):
fl = '`, `'.join(fieldname)

r = self.sql("select `%s` from `tab%s` where name='%s'" % (fl, doctype, docname))
try:
r = self.sql("select `%s` from `tab%s` where name='%s'" % (fl, doctype, docname))
except Exception, e:
if e.args[0]==1054 and ignore:
return None
else:
raise e
return r and (len(r[0]) > 1 and r[0] or r[0][0]) or None
else:
if type(fieldname) in (list, tuple):


+ 5
- 1
cgi-bin/webnotes/model/__init__.py Näytä tiedosto

@@ -76,6 +76,10 @@ def delete_doc(doctype=None, name=None, doclist = None, force=0):
# check if links exist
if not force:
check_if_doc_is_linked(doctype, name)

# remove tags
from webnotes.widgets.tags import clear_tags
clear_tags(doctype, name)
try:
webnotes.conn.sql("delete from `tab%s` where name='%s' limit 1" % (doctype, name))
@@ -86,7 +90,7 @@ def delete_doc(doctype=None, name=None, doclist = None, force=0):
webnotes.msgprint("Cannot delete %s '%s' as it is referenced in another record. You must delete the referred record first" % (doctype, name))
raise e
return 'okay'

#=================================================================================


+ 28
- 29
cgi-bin/webnotes/model/doclist.py Näytä tiedosto

@@ -18,7 +18,7 @@ class DocList:
self.to_docstatus = 0
if dt and dn:
self.load_from_db(dt, dn)
def load_from_db(self, dt, dn):
"""
Load doclist from dt
@@ -34,15 +34,15 @@ class DocList:
doclist = [doc,]
for t in tablefields:
doclist += getchildren(doc.name, t[0], t[1], dt, prefix=prefix)
self.docs = docs
def __iter__(self):
"""
Make this iterable
"""
return self.docs.__iter__()
def from_compressed(self, data, docname):
"""
Expand called from client
@@ -50,13 +50,13 @@ class DocList:
from webnotes.model.utils import expand
self.docs = expand(data)
self.objectify(docname)
def objectify(self, docname=None):
"""
Converts self.docs from a list of dicts to list of Documents
"""
from webnotes.model.doc import Document
self.docs = [Document(fielddata=d) for d in self.docs]
if not docname:
self.doc, self.children = self.docs[0], self.docs[1:]
@@ -69,21 +69,20 @@ class DocList:
self.doc = d
else:
self.children.append(d)
# catch all if no self.doc
if not self.doc:
self.doc, self.children = self.docs[0], self.docs[1:]
def make_obj(self):
"""
Create a DocType object
"""
if self.obj: return self.obj
from webnotes.model.code import get_obj
self.obj = get_obj(doc=self.doc, doclist=self.children)
return self.obj
def next(self):
"""
Next doc
@@ -104,13 +103,13 @@ class DocList:

if (not is_single(self.doc.doctype)) and (not cint(self.doc.fields.get('__islocal'))):
tmp = webnotes.conn.sql("""
SELECT modified FROM `tab%s` WHERE name="%s" for update"""
SELECT modified FROM `tab%s` WHERE name="%s" for update"""
% (self.doc.doctype, self.doc.name))

if tmp and str(tmp[0][0]) != str(self.doc.modified):
webnotes.msgprint("""
Document has been modified after you have opened it.
To maintain the integrity of the data, you will not be able to save your changes.
Document has been modified after you have opened it.
To maintain the integrity of the data, you will not be able to save your changes.
Please refresh this document. [%s/%s]""" % (tmp[0][0], self.doc.modified), raise_exception=1)

def check_permission(self):
@@ -119,7 +118,7 @@ class DocList:
"""
if not self.doc.check_perm(verbose=1):
webnotes.msgprint("Not enough permission to save %s" % self.doc.doctype, raise_exception=1)
def check_links(self):
"""
Checks integrity of links (throws exception if links are invalid)
@@ -130,11 +129,11 @@ class DocList:
ref[d.doctype] = d.make_link_list()

err_list += d.validate_links(ref[d.doctype])
if err_list:
webnotes.msgprint("""[Link Validation] Could not find the following values: %s.
webnotes.msgprint("""[Link Validation] Could not find the following values: %s.
Please correct and resave. Document Not Saved.""" % ', '.join(err_list), raise_exception=1)
def update_timestamps_and_docstatus(self):
"""
Update owner, creation, modified_by, modified, docstatus
@@ -142,17 +141,17 @@ class DocList:
from webnotes.utils import now
ts = now()
user = webnotes.__dict__.get('session', {}).get('user') or 'Administrator'
for d in self.docs:
if self.doc.__islocal:
d.owner = user
d.creation = ts
d.modified_by = user
d.modified = ts
if d.docstatus != 2: # don't update deleted
d.docstatus = self.to_docstatus
def prepare_for_save(self, check_links):
"""
Set owner, modified etc before saving
@@ -175,7 +174,7 @@ class DocList:

from webnotes.model.triggers import fire_event
fire_event(self.doc, method)
def save_main(self):
"""
Save the main doc
@@ -184,7 +183,7 @@ class DocList:
self.doc.save(cint(self.doc.__islocal))
except NameError, e:
webnotes.msgprint('%s "%s" already exists' % (self.doc.doctype, self.doc.name))
# prompt if cancelled
if webnotes.conn.get_value(self.doc.doctype, self.doc.name, 'docstatus')==2:
webnotes.msgprint('[%s "%s" has been cancelled]' % (self.doc.doctype, self.doc.name))
@@ -197,7 +196,7 @@ class DocList:
"""
for d in self.children:
deleted, local = d.fields.get('__deleted',0), d.fields.get('__islocal',0)
if cint(local) and cint(deleted):
pass

@@ -206,7 +205,7 @@ class DocList:
d.parent = self.doc.name # rename if reqd
d.parenttype = self.doc.doctype

d.save(new = cint(local))
d.save(new = cint(local))

def save(self, check_links=1):
"""
@@ -217,7 +216,7 @@ class DocList:
self.save_main()
self.save_children()
self.run_method('on_update')
def submit(self):
"""
Save & Submit - set docstatus = 1, run "on_submit"
@@ -227,7 +226,7 @@ class DocList:
self.to_docstatus = 1
self.save()
self.run_method('on_submit')
def cancel(self):
"""
Cancel - set docstatus 2, run "on_cancel"
@@ -239,7 +238,7 @@ class DocList:
self.save_main()
self.save_children()
self.run_method('on_cancel')
def update_after_submit(self):
"""
Update after submit - some values changed after submit
@@ -260,11 +259,11 @@ def getlist(doclist, parentfield):
"""
import webnotes.model.utils
return webnotes.model.utils.getlist(doclist, parentfield)
def copy_doclist(doclist, no_copy = []):
"""
Make a copy of the doclist
"""
import webnotes.model.utils
return webnotes.model.utils.copy_doclist(doclist, no_copy)

+ 59
- 40
cgi-bin/webnotes/model/utils.py Näytä tiedosto

@@ -1,7 +1,7 @@
"""
Model utilities, unclassified functions
"""
def expand(docs):
"""
Expand a doclist sent from the client side. (Internally used by the request handler)
@@ -25,12 +25,12 @@ def compress(doclist):
"""
Compress a doclist before sending it to the client side. (Internally used by the request handler)

"""
"""
if doclist and hasattr(doclist[0],'fields'):
docs = [d.fields for d in doclist]
else:
docs = doclist
kl, vl = {}, []
for d in docs:
dt = d['doctype']
@@ -38,10 +38,10 @@ def compress(doclist):
fl = d.keys()
forbidden = ['server_code_compiled']
nl = ['doctype','localname','__oldparent','__unsaved']
# add client script for doctype, doctype due to ambiguity
if dt=='DocType': nl.append('__client_script')
for f in fl:
if not (f in nl) and not (f in forbidden):
nl.append(f)
@@ -64,21 +64,24 @@ def compress(doclist):
def getlist(doclist, field):
"""
Filter a list of records for a specific field from the full doclist
Example::
# find all phone call details
# find all phone call details
dl = getlist(self.doclist, 'contact_updates')
pl = []
for d in dl:
if d.type=='Phone':
pl.append(d)
"""
from webnotes.utils import cint
l = []
for d in doclist:
if d.parent and (not d.parent.lower().startswith('old_parent:')) and d.parentfield == field:
l.append(d)

l.sort(lambda a, b: cint(a.idx) - cint(b.idx))

return l

# Copy doclist
@@ -90,31 +93,31 @@ def copy_doclist(doclist, no_copy = []):
Pass fields that are not to be copied in `no_copy`
"""
from webnotes.model.doc import Document
cl = []
# main doc
c = Document(fielddata = doclist[0].fields.copy())
# clear no_copy fields
for f in no_copy:
for f in no_copy:
if c.fields.has_key(f):
c.fields[f] = None
c.name = None
c.save(1)
cl.append(c)
# new parent name
parent = c.name
# children
for d in doclist[1:]:
c = Document(fielddata = d.fields.copy())
c.name = None
# clear no_copy fields
for f in no_copy:
for f in no_copy:
if c.fields.has_key(f):
c.fields[f] = None

@@ -138,18 +141,18 @@ def _make_html(doc, link_list):
from webnotes.utils import cstr
out = '<table class="simpletable">'
for k in doc.fields.keys():
if k!='server_code_compiled':
if k!='server_code_compiled':
v = cstr(doc.fields[k])
# link field
if v and (k in link_list.keys()):
dt = link_list[k]
if type(dt)==str and dt.startswith('link:'):
dt = dt[5:]
v = '<a href="index.cgi?page=Form/%s/%s">%s</a>' % (dt, v, v)
v = '<a href="index.cgi?page=Form/%s/%s">%s</a>' % (dt, v, v)
out += '\t<tr><td>%s</td><td>%s</td></tr>\n' % (cstr(k), v)
out += '</table>'
return out

@@ -159,13 +162,13 @@ def to_html(doclist):
"""
out = ''
link_lists = {}
for d in doclist:
if not link_lists.get(d.doctype):
link_lists[d.doctype] = d.make_link_list()

out += _make_html(d, link_lists[d.doctype])
return out

def commonify_doclist(doclist, with_comments=1):
@@ -183,15 +186,17 @@ def commonify_doclist(doclist, with_comments=1):
c[k] = doclist[0][k]
return c

def strip_common(d):
for k in common_keys:
def strip_common_and_idx(d):
for k in common_keys:
if k in d: del d[k]
if 'idx' in d: del d['idx']
return d

def make_common_dicts(doclist):
common_dict = {} # one per doctype
# make common dicts for all records
for d in doclist:
if not d['doctype'] in common_dict:
@@ -206,15 +211,15 @@ def commonify_doclist(doclist, with_comments=1):
common_dict = make_common_dicts(doclist)

# make docs
final = []
final = []
for d in doclist:
f = strip_common(get_diff_dict(common_dict[d['doctype']], d))
f = strip_common_and_idx(get_diff_dict(common_dict[d['doctype']], d))
f['doctype'] = d['doctype'] # keep doctype!
# strip name for child records (only an auto generated number!)
if f['doctype'] != doclist[0]['doctype']:
del f['name']
if with_comments:
f['##comment'] = d['doctype'] + ('name' in f and (', ' + f['name']) or '')
final.append(f)
@@ -225,37 +230,51 @@ def commonify_doclist(doclist, with_comments=1):
d['name']='__common__'
if with_comments:
d['##comment'] = 'These values are common for all ' + d['doctype']
commons.append(strip_common(d))
commons.append(strip_common_and_idx(d))
common_values = make_common(doclist)
return [common_values]+commons+final
def uncommonify_doclist(dl):
"""
Expands an commonified doclist
"""
# first one has common values
common_values = dl[0]
common_dict = {}
final = []
idx_dict = {}

for d in dl[1:]:
if 'name' in d and d['name']=='__common__':
# common for a doctype -
del d['name']
common_dict[d['doctype']] = d
else:
dt = d['doctype']
if not dt in idx_dict: idx_dict[dt] = 0;
d1 = common_values.copy()
d1.update(common_dict[d['doctype']])

# update from common and global
d1.update(common_dict[dt])
d1.update(d)

# idx by sequence
d1['idx'] = idx_dict[dt]
# increment idx
idx_dict[dt] += 1

final.append(d1)

return final
def pprint_doclist(doclist, with_comments = 1):
"""
Pretty Prints a doclist with common keys separated and comments
"""
from webnotes.utils import pprint_dict
dictlist =[pprint_dict(d) for d in commonify_doclist(doclist, with_comments)]
title = '# '+doclist[0]['doctype']+', '+doclist[0]['name']
return title + '\n[\n' + ',\n'.join(dictlist) + '\n]'
@@ -268,5 +287,5 @@ def peval_doclist(txt):
return uncommonify_doclist(eval(txt))
else:
return eval(txt)
return uncommonify_doclist(eval(txt))

+ 15
- 12
cgi-bin/webnotes/modules/__init__.py Näytä tiedosto

@@ -139,8 +139,13 @@ class Module:
"""
Sync the file to the db
"""
import os
dt, dn = scrub_dt_dn(dt, dn)
self.get_file(dt, dn, dn + '.txt').sync()
path = os.path.exists(os.path.join(self.get_path(), os.path.join(dt, dn, dn + '.txt')))
if not path:
webnotes.msgprint("%s not found" % path)
else:
self.get_file(dt, dn, dn + '.txt').sync(force=1)
def sync_all_of_type(self, extn, verbose=0):
"""
@@ -217,15 +222,13 @@ class ModuleFile:
"""
returns file contents
"""
try:
import os
if os.path.exists(self.path):
f = open(self.path,'r')
self.content = f.read()
f.close()
except IOError, e:
if e.args[0]==2:
self.content = ''
else:
raise e
else:
self.content = ''

return self.content
@@ -248,21 +251,21 @@ class TxtModuleFile(ModuleFile):
def __init__(self, path):
ModuleFile.__init__(self, path)
def sync(self):
def sync(self, force=1):
"""
import the doclist if new
"""
if self.is_new():
from webnotes.model.utils import peval_doclist
doclist = peval_doclist(self.read())
if doclist:
if doclist:
from webnotes.utils.transfer import set_doc
set_doc(doclist, 1, 1, 1)

# since there is a new timestamp on the file, update timestamp in
# the record
webnotes.conn.sql("update `tab%s` set modified=now() where name=%s" \
% (doclist[0]['doctype'], '%s'), doclist[0]['name'])
from webnotes.utils.transfer import set_doc
set_doc(doclist, 1, 1, 1)
self.update()


+ 4
- 3
cgi-bin/webnotes/modules/patch.py Näytä tiedosto

@@ -31,6 +31,7 @@ def write_log():
patch_log.write(('\n\nError in %s:\n' % webnotes.conn.cur_db_name) + webnotes.getTraceback())
patch_log.close()
webnotes.msgprint("There were errors in running patches, please call the Administrator")
from webnotes.utils import sendmail
subj = 'Error in running patches in %s' % webnotes.conn.cur_db_name
msg = subj + '<br><br>Login User: ' + webnotes.user.name + '<br><br>' + webnotes.getTraceback()
sendmail(['developer@erpnext.com'], sender='automail@erpnext.com', subject= subj, parts=[['text/plain', msg]])

+ 6
- 2
cgi-bin/webnotes/utils/__init__.py Näytä tiedosto

@@ -119,7 +119,7 @@ def getdate(string_date):
else:
return ''

def add_days(date, days):
def add_days(date, days, format='string'):
"""
Adds `days` to the given `string_date`
"""
@@ -130,7 +130,11 @@ def add_days(date, days):
if type(date) not in (datetime.datetime, datetime.date):
date = getdate(date)

return (date + datetime.timedelta(days)).strftime('%Y-%m-%d')
dt = date + datetime.timedelta(days)
if format=='string':
return dt.strftime('%Y-%m-%d')
else:
return dt

def add_months(string_date, months):
import datetime


+ 14
- 1
cgi-bin/webnotes/utils/backups.py Näytä tiedosto

@@ -123,7 +123,7 @@ def get_backup():
"""
#if verbose: print webnotes.conn.cur_db_name + " " + webnotes.defs.db_password
odb = BackupGenerator(webnotes.conn.cur_db_name, webnotes.conn.cur_db_name,\
webnotes.defs.db_password)
get_db_password(webnotes.conn.cur_db_name))
recipient_list = odb.get_backup()
delete_temp_backups()
webnotes.msgprint("""A download link to your backup will be emailed \
@@ -131,6 +131,19 @@ def get_backup():
%s""" % (', '.join(recipient_list)))


def get_db_password(db_name):
"""
Get db password from defs
"""
from webnotes import defs
if hasattr(defs, 'get_db_password'):
return defs.get_db_password(db_name)

if hasattr(defs, 'db_password'):
return defs.db_password



def delete_temp_backups():
"""
Cleans up the backup_link_path directory by deleting files older than 24 hours


+ 9
- 3
cgi-bin/webnotes/utils/email_lib/receive.py Näytä tiedosto

@@ -39,8 +39,11 @@ class IncomingMail:
"""
get utf-8 encoded part content
"""
return unicode(part.get_payload(decode=True),str(charset),"ignore").encode('utf8','replace')
try:
return unicode(part.get_payload(decode=True),str(charset),"ignore").encode('utf8','replace')
except LookupError, e:
return part.get_payload()

def get_attachment(self, part, charset):
"""
Extracts an attachment
@@ -128,7 +131,10 @@ class POP3Mailbox:
num = len(self.pop.list()[1])
for m in range(num):
msg = self.pop.retr(m+1)
self.process_message(IncomingMail('\n'.join(msg[1])))
try:
self.process_message(IncomingMail('\n'.join(msg[1])))
except:
pass
self.pop.dele(m+1)
self.pop.quit()


+ 1
- 1
cgi-bin/webnotes/utils/scheduler.py Näytä tiedosto

@@ -89,7 +89,7 @@ class Scheduler:
import webnotes, webnotes.defs, webnotes.db

try:
webnotes.conn = webnotes.db.Database(user=db_name, password=webnotes.defs.db_password)
webnotes.conn = webnotes.db.Database(user=db_name, password=webnotes.get_db_password(db_name))
webnotes.session = {'user':'Administrator'}

module = '.'.join(event.split('.')[:-1])


+ 1
- 1
cgi-bin/webnotes/widgets/page.py Näytä tiedosto

@@ -19,7 +19,7 @@ class Page:
Loads page info from files in module
"""
# load js
doc.fields['__script'] = module.get_doc_file('page',doc.name,'.js').read()
doc.fields['__script'] = module.get_doc_file('page',doc.name,'.js').read() or doc.script
doc.script = None

# load css


+ 48
- 48
cgi-bin/webnotes/widgets/query_builder.py Näytä tiedosto

@@ -14,7 +14,7 @@ def get_search_criteria_list(dt):
def load_report_list():
webnotes.response['rep_list'] = get_search_criteria_list(form.getvalue('dt'))

# Get, scrub metadata
# ====================================================================

@@ -37,20 +37,20 @@ def get_parent_dt(dt):

def get_sql_meta(tl):
std_columns = {
'owner':('Owner', '', '', '100'),
'creation':('Created on', 'Date', '', '100'),
'modified':('Last modified on', 'Date', '', '100'),
'owner':('Owner', '', '', '100'),
'creation':('Created on', 'Date', '', '100'),
'modified':('Last modified on', 'Date', '', '100'),
'modified_by':('Modified By', '', '', '100')
}
meta = {}
for dt in tl:
meta[dt] = std_columns.copy()

# for table doctype, the ID is the parent id
pdt = get_parent_dt(dt)
if pdt:
if pdt:
meta[dt]['parent'] = ('ID', 'Link', pdt, '200')

# get the field properties from DocField
@@ -58,10 +58,10 @@ def get_sql_meta(tl):
for r in res:
if r[0]:
meta[dt][r[0]] = (r[1], r[2], r[3], r[4]);
# name
meta[dt]['name'] = ('ID', 'Link', dt, '200')
return meta

# Additional conditions to fulfill match permission rules
@@ -80,12 +80,12 @@ def getmatchcondition(dt, ud, ur):
return ''

return ' OR '.join(cond)
def add_match_conditions(q, tl, ur, ud):
sl = []
for dt in tl:
s = getmatchcondition(dt, ud, ur)
if s:
if s:
sl.append(s)

# insert the conditions
@@ -94,13 +94,13 @@ def add_match_conditions(q, tl, ur, ud):

condition_end = q.find('ORDER BY')!=-1 and 'ORDER BY' or 'LIMIT'
condition_end = q.find('GROUP BY')!=-1 and 'GROUP BY' or condition_end
if q.find('ORDER BY')!=-1 or q.find('LIMIT')!=-1 or q.find('GROUP BY')!=-1: # if query continues beyond conditions
q = q.split(condition_end)
q = q[0] + condition_st + '(' + ' OR '.join(sl) + ') ' + condition_end + q[1]
else:
q = q + condition_st + '(' + ' OR '.join(sl) + ')'
return q

# execute server-side script from Search Criteria
@@ -111,7 +111,7 @@ def exec_report(code, res, colnames=[], colwidths=[], coltypes=[], coloptions=[]
for c in colnames:
col_idx[c] = i
i+=1
# load globals (api)
from webnotes import *
from webnotes.utils import *
@@ -127,12 +127,12 @@ def exec_report(code, res, colnames=[], colwidths=[], coltypes=[], coloptions=[]
NEWLINE = '\n'

exec str(code)
if out!=None:
res = out

return res, style, header_html, footer_html, page_template
# ====================================================================

def guess_type(m):
@@ -146,7 +146,7 @@ def guess_type(m):
return 'Date'
else:
return 'Data'
def build_description_simple():
colnames, coltypes, coloptions, colwidths = [], [], [], []

@@ -155,7 +155,7 @@ def build_description_simple():
coltypes.append(guess_type[m[0]])
coloptions.append('')
colwidths.append('100')
return colnames, coltypes, coloptions, colwidths

# ====================================================================
@@ -180,27 +180,27 @@ def build_description_standard(meta, tl):

if (not dt) and merged_meta.get(fn):
# no "AS" given, find type from merged description
desc = merged_meta[fn]
colnames.append(desc[0] or fn)
coltypes.append(desc[1] or '')
coloptions.append(desc[2] or '')
colwidths.append(desc[3] or '100')
elif meta.get(dt,{}).has_key(fn):
# type specified for a multi-table join
# usually from Report Builder
desc = meta[dt][fn]
colnames.append(desc[0] or fn)
coltypes.append(desc[1] or '')
coloptions.append(desc[2] or '')
colwidths.append(desc[3] or '100')
else:
# nothing found
# guess
colnames.append(fn)
coltypes.append(guess_type(f[1]))
coloptions.append('')
@@ -214,21 +214,21 @@ def build_description_standard(meta, tl):
def runquery(q='', ret=0, from_export=0):
import webnotes.utils

formatted = cint(form.getvalue('formatted'))
formatted = cint(form.getvalue('formatted'))
# CASE A: Simple Query
# --------------------
if form.getvalue('simple_query') or form.getvalue('is_simple'):
q = form.getvalue('simple_query') or form.getvalue('query')
if not q: q = form.getvalue('simple_query') or form.getvalue('query')
if q.split()[0].lower() != 'select':
raise Exception, 'Query must be a SELECT'
as_dict = cint(form.getvalue('as_dict'))
res = sql(q, as_dict = as_dict, as_list = not as_dict, formatted=formatted)
# build colnames etc from metadata
colnames, coltypes, coloptions, colwidths = [], [], [], []
# CASE B: Standard Query
# -----------------------
else:
@@ -236,17 +236,17 @@ def runquery(q='', ret=0, from_export=0):

tl = get_sql_tables(q)
meta = get_sql_meta(tl)
q = add_match_conditions(q, tl, webnotes.user.roles, webnotes.user.get_defaults())
# replace special variables
q = q.replace('__user', session['user'])
q = q.replace('__today', webnotes.utils.nowdate())
res = sql(q, as_list=1, formatted=formatted)

colnames, coltypes, coloptions, colwidths = build_description_standard(meta, tl)
# run server script
# -----------------
style, header_html, footer_html, page_template = '', '', '', ''
@@ -254,15 +254,15 @@ def runquery(q='', ret=0, from_export=0):
sc_id = form.getvalue('sc_id')
from webnotes.model.code import get_code
sc_details = webnotes.conn.sql("select module, standard, server_script from `tabSearch Criteria` where name=%s", sc_id)[0]
if sc_details[1]!='No':
if sc_details[1]!='No':
code = get_code(sc_details[0], 'Search Criteria', sc_id, 'py')
else:
code = sc_details[2]
if code:
filter_values = form.has_key('filter_values') and eval(form.getvalue('filter_values','')) or {}
res, style, header_html, footer_html, page_template = exec_report(code, res, colnames, colwidths, coltypes, coloptions, filter_values, q, from_export)
out['colnames'] = colnames
out['coltypes'] = coltypes
out['coloptions'] = coloptions
@@ -270,17 +270,17 @@ def runquery(q='', ret=0, from_export=0):
out['header_html'] = header_html
out['footer_html'] = footer_html
out['page_template'] = page_template
if style:
out['style'] = style
# just the data - return
if ret==1:
return res
return res

out['values'] = res

# return num of entries
# return num of entries
qm = form.has_key('query_max') and form.getvalue('query_max') or ''
if qm and qm.strip():
if qm.split()[0].lower() != 'select':
@@ -298,31 +298,31 @@ def runquery_csv():

# run query
res = runquery(from_export = 1)
q = form.getvalue('query')
rep_name = form.getvalue('report_name')
if not form.has_key('simple_query'):

# Report Name
if not rep_name:
rep_name = get_sql_tables(q)[0]
if not rep_name: rep_name = 'DataExport'
# Headings
heads = []
rows = [[rep_name], out['colnames']] + out['values']
from cStringIO import StringIO
import csv
f = StringIO()
writer = csv.writer(f)
for r in rows:
writer.writerow(r)
f.seek(0)
out['result'] = f.read()
out['type'] = 'csv'


+ 9
- 9
cgi-bin/webnotes/widgets/search.py Näytä tiedosto

@@ -22,16 +22,16 @@ def getsearchfields():
webnotes.response['searchfields'] = [['name', 'ID', 'Data', '']] + res

def make_query(fields, dt, key, txt, start, length):
return """SELECT %(fields)s
FROM `tab%(dt)s`
return """SELECT %(fields)s
FROM `tab%(dt)s`
WHERE `tab%(dt)s`.`%(key)s` LIKE '%(txt)s' AND `tab%(dt)s`.docstatus != 2
ORDER BY `tab%(dt)s`.`%(key)s`
ORDER BY `tab%(dt)s`.`%(key)s`
DESC LIMIT %(start)s, %(len)s """ % {
'fields': fields,
'dt': dt,
'key': key,
'txt': txt + '%',
'start': start,
'start': start,
'len': length
}

@@ -48,7 +48,7 @@ def get_std_fields_list(dt, key):

def build_for_autosuggest(res):
from webnotes.utils import cstr
results = []
for r in res:
info = ''
@@ -56,10 +56,10 @@ def build_for_autosuggest(res):
info = ','.join([cstr(t) for t in r[1:]])
if len(info) > 30:
info = info[:30] + '...'
results.append({'id':r[0], 'value':r[0], 'info':info})
return results
def scrub_custom_query(query, key, txt):
if '%(key)s' in query:
query = query.replace('%(key)s', key)
@@ -74,7 +74,7 @@ def search_link():
txt = webnotes.form.getvalue('txt')
dt = webnotes.form.getvalue('dt')
query = webnotes.form.getvalue('query')
if query:
res = webnotes.conn.sql(scrub_custom_query(query, 'name', txt))
else:
@@ -97,5 +97,5 @@ def search_widget():
query = scrub_custom_query(user_query, key, txt)
else:
query = make_query(', '.join(get_std_fields_list(dt, key)), dt, key, txt, webnotes.form.getvalue('start') or 0, webnotes.form.getvalue('page_len') or 50)
webnotes.widgets.query_builder.runquery(query)

+ 25
- 5
cgi-bin/webnotes/widgets/tags.py Näytä tiedosto

@@ -70,7 +70,7 @@ class DocTags:
def get_tags(self, dn):
"""returns tag for a particular item"""
return webnotes.conn.get_value(self.dt, dn, '_user_tags') or ''
return webnotes.conn.get_value(self.dt, dn, '_user_tags', ignore=1) or ''

def create(self, tag):
try:
@@ -95,16 +95,32 @@ class DocTags:
self.update(dn, filter(lambda x:x!=tag, tl))
TagCounter(self.dt).update(tag, -1)

def remove_all(self, dn):
"""remove all user tags (call before delete)"""
tl = self.get_tags(dn).split(',')
tl = filter(lambda x:x, tl)
tc = TagCounter(self.dt)
for t in tl:
tc.update(t, -1)
self.update(dn, [])

def update(self, dn, tl):
"""updates the _user_tag column in the table"""

tl = list(set(filter(lambda x: x, tl)))
if not tl:
tags = ''
else:
tl = list(set(filter(lambda x: x, tl)))
tags = ',' + ','.join(tl)
try:
webnotes.conn.sql("update `tab%s` set _user_tags=%s where name=%s" % \
(self.dt,'%s','%s'), (',' + ','.join(tl), dn))
(self.dt,'%s','%s'), (tags , dn))
except Exception, e:
if e.args[0]==1054:
if not tags:
# no tags, nothing to do
return
self.setup()
self.update(dn, tl)
else: raise e
@@ -141,6 +157,8 @@ class TagCounter:
# if doctype cnt does not exist
# creates it for the first time
def update(self, tag, diff):
if not tag:
return
"updates tag cnt for a doctype and tag"
cnt = webnotes.conn.sql("select cnt from `_tag_cnt` where doctype=%s and tag=%s", (self.doctype, tag))

@@ -255,4 +273,6 @@ def get_top_tags(args=''):
get_item('tags-' + dt).set(tl, 60*60)
return tl

def clear_tags(dt, dn):
DocTags(dt).remove_all(dn)

+ 17
- 14
js/form.compressed.js Näytä tiedosto

@@ -121,7 +121,8 @@ if(this.docname){if(!this.check_doc_perm())return;if(!this.setup_done)this.setup
if(this.doc.__islocal)
this.is_editable[this.docname]=1;this.editable=this.is_editable[this.docname];if(!this.doc.__archived&&(this.editable||(!this.editable&&this.meta.istable))){if(this.print_wrapper){$dh(this.print_wrapper);$ds(this.page_layout.wrapper);}
if(!this.meta.istable){this.refresh_header();this.sidebar&&this.sidebar.refresh();}
this.runclientscript('refresh');this.refresh_tabs();this.refresh_fields();this.refresh_dependency();this.refresh_footer();if(this.layout)this.layout.show();if(is_onload)
this.runclientscript('refresh');$(document).trigger('form_refresh')
this.refresh_tabs();this.refresh_fields();this.refresh_dependency();this.refresh_footer();if(this.layout)this.layout.show();if(is_onload)
this.runclientscript('onload_post_render',this.doctype,this.docname);}else{this.refresh_header();if(this.print_wrapper){this.refresh_print_layout();}
this.runclientscript('edit_status_changed');}
if(!this.display)this.show_the_frm();if(!this.meta.in_dialog)page_body.change_to('Forms');}}
@@ -252,22 +253,25 @@ this.input.onchange=function(){if(me.editor){}else{me.set(me.input.value);}
me.run_trigger();}
this.get_value=function(){if(me.editor){return me.editor.getContent();}else{return this.input.value;}}
if(this.df.fieldtype=='Text Editor'){$(me.input).tinymce({script_url:'js/tiny_mce_33/tiny_mce.js',theme:"advanced",plugins:"style,inlinepopups,table",extended_valid_elements:"div[id|dir|class|align|style]",width:'100%',height:'360px',theme_advanced_buttons1:"bold,italic,underline,strikethrough,hr,|,justifyleft,justifycenter,justifyright,|,formatselect,fontselect,fontsizeselect",theme_advanced_buttons2:"bullist,numlist,|,outdent,indent,|,undo,redo,|,link,unlink,code,|,forecolor,backcolor,|,tablecontrols",theme_advanced_buttons3:"",theme_advanced_toolbar_location:"top",theme_advanced_toolbar_align:"left",content_css:"js/tiny_mce_33/custom_content.css",oninit:function(){me.init_editor();}});}else{$y(me.input,{fontFamily:'Courier, Fixed'});}}
_f.CodeField.prototype.init_editor=function(){var me=this;this.editor=tinymce.get(this.myid);this.editor.onKeyUp.add(function(ed,e){me.set(ed.getContent());});this.editor.onPaste.add(function(ed,e){me.set(ed.getContent());});this.editor.onSetContent.add(function(ed,e){me.set(ed.getContent());});if(cur_frm)this.editor.setContent(locals[cur_frm.doctype][cur_frm.docname][this.df.fieldname]);}
_f.CodeField.prototype.init_editor=function(){var me=this;this.editor=tinymce.get(this.myid);this.editor.onKeyUp.add(function(ed,e){me.set(ed.getContent());});this.editor.onPaste.add(function(ed,e){me.set(ed.getContent());});this.editor.onSetContent.add(function(ed,e){me.set(ed.getContent());});var c=locals[cur_frm.doctype][cur_frm.docname][this.df.fieldname];if(cur_frm&&c){this.editor.setContent(c);}}
_f.CodeField.prototype.set_disp=function(val){$y(this.disp_area,{width:'90%'})
if(this.df.fieldtype=='Text Editor'){this.disp_area.innerHTML=val;}else{this.disp_area.innerHTML='<textarea class="code_text" readonly=1>'+val+'</textarea>';}}
_f.cur_grid_cell=null;_f.Grid=function(parent){}
_f.Grid.prototype.init=function(parent,row_height){this.alt_row_bg='#F2F2FF';this.row_height=row_height;if(!row_height)this.row_height='26px';this.make_ui(parent);this.insert_column('','','Int','Sr','50px','',[1,0,0]);this.total_width=50;if(this.oninit)this.oninit();keypress_observers.push(this)}
_f.Grid.prototype.init=function(parent,row_height){this.col_idx_by_name={}
this.alt_row_bg='#F2F2FF';this.row_height=row_height;if(!row_height)this.row_height='26px';this.make_ui(parent);this.insert_column('','','Int','Sr','50px','',[1,0,0]);if(this.oninit)this.oninit();keypress_observers.push(this);}
_f.Grid.prototype.make_ui=function(parent){var ht=make_table($a(parent,'div'),1,2,'100%',['60%','40%']);this.main_title=$td(ht,0,0);this.main_title.className='columnHeading';$td(ht,0,1).style.textAlign='right';this.tbar_div=$a($td(ht,0,1),'div','grid_tbarlinks');if(isIE)$y(this.tbar_div,{width:'200px'});this.tbar_tab=make_table(this.tbar_div,1,4,'100%',['25%','25%','25%','25%']);this.wrapper=$a(parent,'div','grid_wrapper');$h(this.wrapper,cint(screen.width*0.5)+'px');this.head_wrapper=$a(this.wrapper,'div','grid_head_wrapper');this.head_tab=$a(this.head_wrapper,'table','grid_head_table');this.head_row=this.head_tab.insertRow(0);this.tab_wrapper=$a(this.wrapper,'div','grid_tab_wrapper');this.tab=$a(this.tab_wrapper,'table','grid_table');var me=this;this.wrapper.onscroll=function(){me.head_wrapper.style.top=me.wrapper.scrollTop+'px';}}
_f.Grid.prototype.show=function(){if(this.can_add_rows){$ds(this.tbar_div);}else{$dh(this.tbar_div);}
$ds(this.wrapper);}
_f.Grid.prototype.hide=function(){$dh(this.wrapper);$dh(this.tbar_div);}
_f.Grid.prototype.insert_column=function(doctype,fieldname,fieldtype,label,width,options,perm,reqd){var idx=this.head_row.cells.length;if(!width)width='100px';var col=this.head_row.insertCell(idx);col.doctype=doctype;col.fieldname=fieldname;col.fieldtype=fieldtype;col.innerHTML='<div>'+label+'</div>';col.label=label;if(reqd)
col.childNodes[0].style.color="#D22";this.total_width+=cint(width);$w(col,width);col.orig_width=col.style.width;col.options=options;col.perm=perm;}
_f.Grid.prototype.set_column_disp=function(label,show){for(var i=0;i<this.head_row.cells.length;i++){var c=this.head_row.cells[i];if(label&&(c.label==label||c.cur_label==label)){if(show){var w=c.orig_width;this.head_tab.style.width=(this.total_width+cint(w))+'px';this.tab.style.width=(this.total_width+cint(w))+'px';}else{var w='0px';this.head_tab.style.width=(this.total_width-cint(c.orig_width))+'px';this.tab.style.width=(this.total_width-cint(c.orig_width))+'px';}
$w(c,w);if(this.tab){for(var j=0;j<this.tab.rows.length;j++){var cell=this.tab.rows[j].cells[i];$w(cell,w);if(show){$ds(cell.div);cell.div.style.padding='2px';}
else{$dh(cell.div);cell.div.style.padding='0px';}}}
break;}}}
_f.Grid.prototype.append_row=function(idx,docname){if(!idx)idx=this.tab.rows.length;var row=this.tab.insertRow(idx);row.docname=docname;if(idx%2)var odd=true;else var odd=false;var me=this;for(var i=0;i<this.head_row.cells.length;i++){var cell=row.insertCell(i);var hc=this.head_row.cells[i];$w(cell,hc.style.width);cell.row=row;cell.grid=this;cell.className='grid_cell';cell.div=$a(cell,'div','grid_cell_div');if(this.row_height){cell.div.style.height=this.row_height;}
_f.Grid.prototype.insert_column=function(doctype,fieldname,fieldtype,label,width,options,perm,reqd){var idx=this.head_row.cells.length;if(!width)width='140px';if((width+'').slice(-2)!='px'){width=width+'px';}
var col=this.head_row.insertCell(idx);col.doctype=doctype;col.fieldname=fieldname;col.fieldtype=fieldtype;col.innerHTML='<div>'+label+'</div>';col.label=label;if(reqd)
col.childNodes[0].style.color="#D22";col.style.width=width;col.options=options;col.perm=perm;this.col_idx_by_name[fieldname]=idx;}
_f.Grid.prototype.reset_table_width=function(){var w=0;for(var i=0,len=this.head_row.cells.length;i<len;i++){w+=cint(this.head_row.cells[i].style.width);}
this.head_tab.style.width=w+'px';this.tab.style.width=w+'px';}
_f.Grid.prototype.set_column_disp=function(fieldname,show){var cidx=this.col_idx_by_name[fieldname];if(!cidx){msgprint('Trying to hide unknown column: '+fieldname);return;}
var disp=show?'table-cell':'none';this.head_row.cells[cidx].style.display=disp;for(var i=0,len=this.tab.rows.length;i<len;i++){var cell=this.tab.rows[i].cells[cidx];cell.style.display=disp;}
this.reset_table_width();}
_f.Grid.prototype.append_row=function(idx,docname){if(!idx)idx=this.tab.rows.length;var row=this.tab.insertRow(idx);row.docname=docname;if(idx%2)var odd=true;else var odd=false;var me=this;for(var i=0;i<this.head_row.cells.length;i++){var cell=row.insertCell(i);var hc=this.head_row.cells[i];cell.style.width=hc.style.width;cell.style.display=hc.style.display;cell.row=row;cell.grid=this;cell.className='grid_cell';cell.div=$a(cell,'div','grid_cell_div');if(this.row_height){cell.div.style.height=this.row_height;}
cell.div.cell=cell;cell.div.onclick=function(e){me.cell_click(this.cell,e);}
if(odd){$bg(cell,this.alt_row_bg);cell.is_odd=1;cell.div.style.border='2px solid '+this.alt_row_bg;}else $bg(cell,'#FFF');if(!hc.fieldname)cell.div.style.cursor='default';}
this.set_ht();return row;}
@@ -299,7 +303,7 @@ return;if(!_f.cur_grid_cell)return;if(_f.cur_grid_cell.grid!=this)return;var ri=
_f.Grid.prototype.make_template=function(hc){hc.template=make_field(get_field(hc.doctype,hc.fieldname),hc.doctype,'',this.field.frm,true);hc.template.grid=this;}
_f.Grid.prototype.append_rows=function(n){for(var i=0;i<n;i++)this.append_row();}
_f.Grid.prototype.truncate_rows=function(n){for(var i=0;i<n;i++)this.tab.deleteRow(this.tab.rows.length-1);}
_f.Grid.prototype.set_data=function(data){this.cell_deselect();this.tab.style.width=this.total_width+'px';this.head_tab.style.width=this.total_width+'px';if(data.length>this.tab.rows.length)
_f.Grid.prototype.set_data=function(data){this.cell_deselect();this.reset_table_width();if(data.length>this.tab.rows.length)
this.append_rows(data.length-this.tab.rows.length);if(data.length<this.tab.rows.length)
this.truncate_rows(this.tab.rows.length-data.length);for(var ridx=0;ridx<data.length;ridx++){this.refresh_row(ridx,data[ridx]);}
if(this.can_add_rows&&this.make_newrow){this.make_newrow();}
@@ -315,8 +319,7 @@ $td(t,0,0).isactive=1;$td(t,0,1).isactive=1;l.isactive=1;div.isactive=1;img.isac
_f.FormGrid.prototype.make_buttons=function(){var me=this;this.tbar_btns={};this.tbar_btns['Del']=this.make_tbar_link($td(this.tbar_tab,0,0),'Del',function(){me.delete_row();},'ic-round_minus');this.tbar_btns['Ins']=this.make_tbar_link($td(this.tbar_tab,0,1),'Ins',function(){me.insert_row();},'ic-round_plus');this.tbar_btns['Up']=this.make_tbar_link($td(this.tbar_tab,0,2),'Up',function(){me.move_row(true);},'ic-arrow_top');this.tbar_btns['Dn']=this.make_tbar_link($td(this.tbar_tab,0,3),'Dn',function(){me.move_row(false);},'ic-arrow_bottom');for(var i in this.btns)
this.btns[i].isactive=true;}
_f.FormGrid.prototype.make_columns=function(){var gl=fields_list[this.field.df.options];if(!gl){alert('Table details not found "'+this.field.df.options+'"');}
gl.sort(function(a,b){return a.idx-b.idx});var p=this.field.perm;for(var i=0;i<gl.length;i++){if(p[this.field.df.permlevel]&&p[this.field.df.permlevel][READ]&&(!gl[i].hidden)){this.insert_column(this.field.df.options,gl[i].fieldname,gl[i].fieldtype,gl[i].label,gl[i].width,gl[i].options,this.field.perm,gl[i].reqd);}}
for(var i=0;i<this.head_row.cells.length;i++){var c=this.head_row.cells[i];$w(c,cint(cint(c.style.width)/this.total_width*100)+'%')}}
gl.sort(function(a,b){return a.idx-b.idx});var p=this.field.perm;for(var i=0;i<gl.length;i++){if(p[this.field.df.permlevel]&&p[this.field.df.permlevel][READ]){this.insert_column(this.field.df.options,gl[i].fieldname,gl[i].fieldtype,gl[i].label,gl[i].width,gl[i].options,this.field.perm,gl[i].reqd);if(gl[i].hidden){this.set_column_disp(gl[i].fieldname,false);}}}}
_f.FormGrid.prototype.set_column_label=function(fieldname,label){for(var i=0;i<this.head_row.cells.length;i++){var c=this.head_row.cells[i];if(c.fieldname==fieldname){c.innerHTML='<div class="grid_head_div">'+label+'</div>';c.cur_label=label;break;}}}
_f.FormGrid.prototype.refresh=function(){var docset=getchildren(this.doctype,this.field.frm.docname,this.field.df.fieldname,this.field.frm.doctype);var data=[];for(var i=0;i<docset.length;i++){locals[this.doctype][docset[i].name].idx=i+1;data[data.length]=docset[i].name;}
this.set_data(data);}
@@ -495,4 +498,4 @@ wn.widgets.form.file_upload_done=function(doctype,docname,fileid,filename,at_id,
fl.push(filename+','+fileid)
doc.file_list=fl.join('\n');}
else
doc.file_list=filename+','+fileid;doc.modified=new_timestamp;var frm=frms[doctype];frm.attachments.dialog.hide();msgprint('File Uploaded Sucessfully.');frm.refresh();}
doc.file_list=filename+','+fileid;doc.modified=new_timestamp;var frm=frms[doctype];frm.attachments.dialog.hide();msgprint('File Uploaded Sucessfully.');frm.refresh();}

+ 1
- 1
js/webpage/page.js Näytä tiedosto

@@ -56,7 +56,7 @@ function render_page(page_name, menuitem) {
p.doc = pdoc;

if(script) {
try { eval(script); } catch(e) { submit_error(e); }
eval(script);
}

// change


+ 35
- 28
js/webpage/search.js Näytä tiedosto

@@ -21,8 +21,8 @@ function makeselector() {
['Button', 'Search'],
['HTML', 'Help'],
['HTML', 'Result']
]);
]);
// search with
var inp = d.widgets['Beginning With'];
var field_sel = d.widgets['Search By'];
@@ -39,7 +39,7 @@ function makeselector() {
}
d.style = 'Link';
d.set_query_description()
if(!d.sel_type)d.sel_type = 'Value';
d.set_title('Select a "'+ d.sel_type +'" for field "'+label+'"');
}
@@ -47,18 +47,18 @@ function makeselector() {
if(d.style!='Search') {
d.rows['Result'].innerHTML ='';
d.values_len = 0;
}
}
d.style = 'Search';
if(d.input) { d.input = null; sel_type = null; }
d.sel_type = get_label_doctype(dt);
d.set_title('Quick Search for ' + dt);
}
inp.onkeydown = function(e) {
inp.onkeydown = function(e) {
if(isIE)var kc = window.event.keyCode;
else var kc = e.keyCode;

if(kc==13) if(!btn.disabled)btn.onclick();
if(kc==13) if(!btn.disabled)btn.onclick();
}

d.set_query_description = function() {
@@ -68,18 +68,18 @@ function makeselector() {
d.rows['Help'].innerHTML =''
}
}
d.onshow = function() {
d.onshow = function() {
if(d.set_doctype!=d.sel_type) {
d.rows['Result'].innerHTML ='';
d.values_len = 0;
}
inp.value = '';
inp.value = '';
if(d.input && d.input.txt.value) {
inp.value = d.input.txt.value;
}
try{inp.focus();} catch(e){}
if(d.input) d.input.set_get_query();

// temp function to strip labels from search fields
@@ -88,10 +88,10 @@ function makeselector() {
for(var i=0; i<lf.length; i++) l.push(lf[i][1]);
return l;
}
// set fields
$ds(d.rows['Search By']);
if(search_fields[d.sel_type]) {
empty_select(field_sel);
add_sel_options(field_sel, get_sf_list(d.sel_type), 'ID');
@@ -121,8 +121,11 @@ function makeselector() {
this.set_working();
d.set_doctype = d.sel_type;
var q = '';
args = {};

if(d.input && d.input.get_query) {
var doc = {};
args.is_simple = 1;
if(cur_frm) doc = locals[cur_frm.doctype][cur_frm.docname];
var q = d.input.get_query(doc, d.input.doctype, d.input.docname);
if(!q) { return ''; }
@@ -131,21 +134,25 @@ function makeselector() {
// for field type, return field name
var get_sf_fieldname = function(v) {
var lf = search_fields[d.sel_type];
// still loading options
if(!lf)
return 'name'
for(var i=0; i<lf.length; i++) if(lf[i][1]==v) return lf[i][0];
}

$c('webnotes.widgets.search.search_widget',
args = {
'txt':strip(inp.value)
,'doctype':d.sel_type
,'query':q
,'searchfield':get_sf_fieldname(sel_val(field_sel))
},
}

// build args
$.extend(args, {
'txt':strip(inp.value)
,'doctype':d.sel_type
,'query':q
,'searchfield':get_sf_fieldname(sel_val(field_sel))
});

// run the query
$c('webnotes.widgets.search.search_widget',
args,
function(r, rtxt) {
btn.done_working();
if(r.coltypes)r.coltypes[0]='Link'; // first column must always be selectable even if it is not a link
@@ -153,7 +160,7 @@ function makeselector() {
d.set_result(r);
}, function() { btn.done_working(); });
}
d.set_result = function(r) {
d.rows['Result'].innerHTML = '';
var c = $a(d.rows['Result'],'div','comment',{paddingBottom:'4px',marginBottom:'4px',borderBottom:'1px solid #CCC', marginLeft:'4px'});
@@ -178,8 +185,8 @@ function makeselector() {
for(var j=1; j<r.values[i].length; j++) cl.push(r.values[i][j]);
var c = $a(div,'div','comment',{marginTop:'2px'}); c.innerHTML = cl.join(', ');
}
}
selector = d;
selector = d;
}

+ 5
- 0
js/widgets/form/form.js Näytä tiedosto

@@ -622,6 +622,11 @@ _f.Frm.prototype.refresh = function(docname) {
// call trigger
this.runclientscript('refresh');
// trigger global trigger
// to use this
// $(docuemnt).bind('form_refresh', function() { })
$(document).trigger('form_refresh')
// tabs
this.refresh_tabs();


+ 4
- 1
js/widgets/form/form_fields.js Näytä tiedosto

@@ -468,7 +468,10 @@ _f.CodeField.prototype.init_editor = function() {
});
// reset content
if(cur_frm) this.editor.setContent(locals[cur_frm.doctype][cur_frm.docname][this.df.fieldname]);
var c = locals[cur_frm.doctype][cur_frm.docname][this.df.fieldname];
if(cur_frm && c) {
this.editor.setContent(c);
}
}

_f.CodeField.prototype.set_disp = function(val) {


+ 6
- 7
js/widgets/form/form_grid.js Näytä tiedosto

@@ -67,16 +67,15 @@ _f.FormGrid.prototype.make_columns = function() {

var p = this.field.perm;
for(var i=0;i<gl.length;i++) {
if(p[this.field.df.permlevel] && p[this.field.df.permlevel][READ] && (!gl[i].hidden)) { // if read
if(p[this.field.df.permlevel] && p[this.field.df.permlevel][READ]) { // if read
this.insert_column(this.field.df.options, gl[i].fieldname, gl[i].fieldtype, gl[i].label, gl[i].width, gl[i].options, this.field.perm, gl[i].reqd);
// hide it even if it is hidden at start..
// so that it can be brought back once
if(gl[i].hidden) {
this.set_column_disp(gl[i].fieldname, false);
}
}
}
// set width as percent
for(var i=0;i<this.head_row.cells.length; i++) {
var c = this.head_row.cells[i];
$w(c,cint(cint(c.style.width) / this.total_width * 100)+'%')
}
}

_f.FormGrid.prototype.set_column_label = function(fieldname, label) {


+ 42
- 38
js/widgets/form/grid.js Näytä tiedosto

@@ -5,6 +5,7 @@ _f.Grid = function(parent) { }

_f.Grid.prototype.init = function(parent, row_height) {
this.col_idx_by_name = {}
this.alt_row_bg = '#F2F2FF';
this.row_height = row_height;

@@ -14,11 +15,10 @@ _f.Grid.prototype.init = function(parent, row_height) {
// Sr No
this.insert_column('', '', 'Int', 'Sr', '50px', '', [1,0,0]);
this.total_width = 50;
if(this.oninit)this.oninit();
keypress_observers.push(this)
keypress_observers.push(this);
}

_f.Grid.prototype.make_ui = function(parent) {
@@ -62,8 +62,10 @@ _f.Grid.prototype.hide = function() {
_f.Grid.prototype.insert_column = function(doctype, fieldname, fieldtype, label, width, options, perm, reqd) {
var idx = this.head_row.cells.length;
if(!width)width = '100px';
if(!width)width = '140px';
if((width+'').slice(-2)!='px') {
width= width + 'px';
}
var col = this.head_row.insertCell(idx);
col.doctype = doctype; // for report (fields may be from diff doctypes)
@@ -74,43 +76,42 @@ _f.Grid.prototype.insert_column = function(doctype, fieldname, fieldtype, label,
if(reqd)
col.childNodes[0].style.color = "#D22";
this.total_width += cint(width);
$w(col, width);
col.orig_width = col.style.width;
col.style.width = width;
col.options = options;
col.perm = perm;

this.col_idx_by_name[fieldname] = idx;
}

_f.Grid.prototype.set_column_disp = function(label, show) {
//alert(label);
for(var i=0; i<this.head_row.cells.length; i++) {
var c = this.head_row.cells[i];
if(label && (c.label == label || c.cur_label == label)) {
//alert(c.orig_width);
if(show) {
var w = c.orig_width;
this.head_tab.style.width = (this.total_width + cint(w)) + 'px';
this.tab.style.width = (this.total_width + cint(w)) + 'px';
} else {
var w = '0px';
this.head_tab.style.width = (this.total_width - cint(c.orig_width)) + 'px';
this.tab.style.width = (this.total_width - cint(c.orig_width)) + 'px';
}
$w(c, w);
// change width of table too
if(this.tab) {
for(var j=0; j<this.tab.rows.length; j++) {
var cell = this.tab.rows[j].cells[i];
$w(cell, w);
if(show) { $ds(cell.div); cell.div.style.padding = '2px'; }
else { $dh(cell.div); cell.div.style.padding = '0px'; }
}
}
break;
}
_f.Grid.prototype.reset_table_width = function() {
var w = 0;
for(var i=0, len=this.head_row.cells.length; i<len; i++) {
w += cint(this.head_row.cells[i].style.width);
}
this.head_tab.style.width = w + 'px';
this.tab.style.width = w + 'px';
}

_f.Grid.prototype.set_column_disp = function(fieldname, show) {
var cidx = this.col_idx_by_name[fieldname];
if(!cidx) {
msgprint('Trying to hide unknown column: ' + fieldname);
return;
}
var disp = show ? 'table-cell' : 'none';

// head
this.head_row.cells[cidx].style.display = disp;

// body
for(var i=0, len=this.tab.rows.length; i<len; i++) {
var cell = this.tab.rows[i].cells[cidx];
cell.style.display = disp;
}
// reset table width
this.reset_table_width();
}

_f.Grid.prototype.append_row = function(idx, docname) {
@@ -125,7 +126,11 @@ _f.Grid.prototype.append_row = function(idx, docname) {
for(var i=0; i<this.head_row.cells.length; i++){
var cell = row.insertCell(i);
var hc = this.head_row.cells[i];
$w(cell, hc.style.width);
// ape style of head
cell.style.width = hc.style.width;
cell.style.display = hc.style.display;
cell.row = row;
cell.grid = this;
cell.className = 'grid_cell';
@@ -394,8 +399,7 @@ _f.Grid.prototype.set_data = function(data) {
this.cell_deselect();

// set table widths
this.tab.style.width = this.total_width + 'px';
this.head_tab.style.width = this.total_width + 'px';
this.reset_table_width();

// append if reqd
if(data.length > this.tab.rows.length)


+ 7
- 1
js/widgets/report_builder/report_builder.js Näytä tiedosto

@@ -507,7 +507,13 @@ _r.ReportBuilder.prototype.set_sort_options = function(l) {
empty_select(this.dt.sort_sel);
if(l) sl = add_lists(l, this.orig_sort_list)
if(l) sl = add_lists(l, this.orig_sort_list);
// no sorts, add one
if(!l.length) {
l.push(['ID', 'name'])
}
for(var i=0; i<sl.length; i++) {
this.dt.add_sort_option(sl[i][0], sl[i][1]);
}


+ 3
- 3
js/wnf.compressed.js Näytä tiedosto

@@ -1034,11 +1034,11 @@ $ds(d.rows['Search By']);if(search_fields[d.sel_type]){empty_select(field_sel);a
d.onhide=function(){if(page_body.wntoolbar)
page_body.wntoolbar.search_sel.disabled=0;if(d.input&&d.input.txt)
d.input.txt.onchange()}
btn.onclick=function(){if(this.disabled)return;this.set_working();d.set_doctype=d.sel_type;var q='';if(d.input&&d.input.get_query){var doc={};if(cur_frm)doc=locals[cur_frm.doctype][cur_frm.docname];var q=d.input.get_query(doc,d.input.doctype,d.input.docname);if(!q){return'';}}
btn.onclick=function(){if(this.disabled)return;this.set_working();d.set_doctype=d.sel_type;var q='';args={};if(d.input&&d.input.get_query){var doc={};args.is_simple=1;if(cur_frm)doc=locals[cur_frm.doctype][cur_frm.docname];var q=d.input.get_query(doc,d.input.doctype,d.input.docname);if(!q){return'';}}
var get_sf_fieldname=function(v){var lf=search_fields[d.sel_type];if(!lf)
return'name'
for(var i=0;i<lf.length;i++)if(lf[i][1]==v)return lf[i][0];}
$c('webnotes.widgets.search.search_widget',args={'txt':strip(inp.value),'doctype':d.sel_type,'query':q,'searchfield':get_sf_fieldname(sel_val(field_sel))},function(r,rtxt){btn.done_working();if(r.coltypes)r.coltypes[0]='Link';d.values_len=r.values.length;d.set_result(r);},function(){btn.done_working();});}
$.extend(args,{'txt':strip(inp.value),'doctype':d.sel_type,'query':q,'searchfield':get_sf_fieldname(sel_val(field_sel))});$c('webnotes.widgets.search.search_widget',args,function(r,rtxt){btn.done_working();if(r.coltypes)r.coltypes[0]='Link';d.values_len=r.values.length;d.set_result(r);},function(){btn.done_working();});}
d.set_result=function(r){d.rows['Result'].innerHTML='';var c=$a(d.rows['Result'],'div','comment',{paddingBottom:'4px',marginBottom:'4px',borderBottom:'1px solid #CCC',marginLeft:'4px'});if(r.values.length==50)
c.innerHTML='Showing max 50 results. Use filters to narrow down your search';else
c.innerHTML='Showing '+r.values.length+' resuts.';var w=$a(d.rows['Result'],'div','',{height:'240px',overflow:'auto',margin:'4px'});for(var i=0;i<r.values.length;i++){var div=$a(w,'div','',{marginBottom:'4px',paddingBottom:'4px',borderBottom:'1px dashed #CCC'});var l=$a($a(div,'div'),'span','link_type');l.innerHTML=r.values[i][0];l.link_name=r.values[i][0];l.dt=r.coloptions[0];if(d.input)
@@ -1130,7 +1130,7 @@ pages['_home']=this;return this;}
function render_page(page_name,menuitem){if(!page_name)return;if((!locals['Page'])||(!locals['Page'][page_name])){loadpage('_home');return;}
var pdoc=locals['Page'][page_name];if(pdoc.style)set_style(pdoc.style)
if(pdoc.stylesheet){set_style(locals.Stylesheet[pdoc.stylesheet].stylesheet);stylesheets.push(pdoc.stylesheet);}
var p=new Page(page_name,pdoc._Page__content?pdoc._Page__content:pdoc.content);var script=pdoc.__script?pdoc.__script:pdoc.script;p.doc=pdoc;if(script){try{eval(script);}catch(e){submit_error(e);}}
var p=new Page(page_name,pdoc._Page__content?pdoc._Page__content:pdoc.content);var script=pdoc.__script?pdoc.__script:pdoc.script;p.doc=pdoc;if(script){eval(script);}
page_body.change_to(page_name);try{if(pscript['onload_'+page_name])pscript['onload_'+page_name]();}catch(e){submit_error(e);}
return p;}
function refresh_page(page_name){var fn=function(r,rt){render_page(page_name)}


Ladataan…
Peruuta
Tallenna