Browse Source

refactored javascript models

version-14
Rushabh Mehta 12 years ago
parent
commit
d1dc786401
34 changed files with 552 additions and 673 deletions
  1. +4
    -4
      core/doctype/doctype/doctype.py
  2. +7
    -5
      public/build.json
  3. +2
    -2
      public/js/legacy/globals.js
  4. +0
    -175
      public/js/legacy/model/doclist.js
  5. +0
    -288
      public/js/legacy/model/local_data.js
  6. +2
    -2
      public/js/legacy/utils/handler.js
  7. +1
    -3
      public/js/legacy/webpage/loaders.js
  8. +1
    -1
      public/js/legacy/webpage/search.js
  9. +2
    -2
      public/js/legacy/widgets/form/clientscriptAPI.js
  10. +2
    -2
      public/js/legacy/widgets/form/fields.js
  11. +52
    -133
      public/js/legacy/widgets/form/form.js
  12. +3
    -3
      public/js/legacy/widgets/form/form_grid.js
  13. +2
    -2
      public/js/legacy/widgets/form/form_header.js
  14. +1
    -1
      public/js/legacy/widgets/form/print_format.js
  15. +9
    -14
      public/js/legacy/widgets/report_builder/report_builder.js
  16. +2
    -1
      public/js/legacy/wn/widgets/form/comments.js
  17. +22
    -2
      public/js/wn/meta.js
  18. +99
    -0
      public/js/wn/model/create_new.js
  19. +129
    -0
      public/js/wn/model/doclist.js
  20. +53
    -4
      public/js/wn/model/model.js
  21. +0
    -0
      public/js/wn/model/perm.js
  22. +117
    -0
      public/js/wn/model/sync.js
  23. +3
    -2
      public/js/wn/provide.js
  24. +2
    -2
      public/js/wn/request.js
  25. +1
    -1
      public/js/wn/ui/listing.js
  26. +1
    -1
      public/js/wn/ui/themes.js
  27. +1
    -1
      public/js/wn/ui/toolbar/selector_dialog.js
  28. +1
    -1
      public/js/wn/views/doclistview.js
  29. +2
    -2
      public/js/wn/views/formview.js
  30. +0
    -1
      public/js/wn/views/load_reportview.js
  31. +1
    -1
      webnotes/__init__.py
  32. +5
    -1
      webnotes/utils/file_manager.py
  33. +1
    -0
      webnotes/widgets/form/load.py
  34. +24
    -16
      webnotes/widgets/form/save.py

+ 4
- 4
core/doctype/doctype/doctype.py View File

@@ -26,9 +26,6 @@ import webnotes
from webnotes.utils import now, cint
msgprint = webnotes.msgprint




class DocType:
def __init__(self, doc=None, doclist=[]):
self.doc = doc
@@ -68,6 +65,9 @@ class DocType:
msgprint('<b>Series already in use:</b> The series "%s" is already used in "%s"' % (prefix, used_in[0][0]), raise_exception=1)

def validate(self):
for c in [".", "/", "#", "&", "=", ":", "'", '"']:
if c in self.name:
webnotes.msgprint(c + " not allowed in name", raise_exception=1)
self.validate_series()
self.scrub_field_names()
validate_fields(filter(lambda d: d.doctype=="DocField", self.doclist))
@@ -182,7 +182,7 @@ def validate_fields_for_doctype(doctype):
def validate_fields(fields):
def check_illegal_characters(fieldname):
for c in ['.', ',', ' ', '-', '&', '%', '=', '"', "'", '*', '$',
'(', ')', '[', ']']:
'(', ')', '[', ']', '/']:
if c in fieldname:
webnotes.msgprint("'%s' not allowed in fieldname (%s)" % (c, fieldname))


+ 7
- 5
public/build.json View File

@@ -54,13 +54,10 @@
"lib/public/js/wn/provide.js",
"lib/public/js/wn/assets.js",
"lib/public/js/wn/dom.js",
"lib/public/js/wn/model.js",
"lib/public/js/wn/perm.js",
"lib/public/js/wn/meta.js",
"lib/public/js/wn/misc/user.js",
"lib/public/js/wn/misc/utils.js",
"lib/public/js/lib/public/json2.js",
"lib/public/js/wn/router.js",
"lib/public/js/wn/ui/messages.js",
"lib/public/js/wn/ui/listing.js",
"lib/public/js/wn/views/container.js",
@@ -79,8 +76,6 @@
"lib/public/js/wn/ui/button.js",
"lib/public/js/legacy/widgets/dialog.js",
"lib/public/js/legacy/webpage/loaders.js",
"lib/public/js/legacy/model/local_data.js",
"lib/public/js/legacy/model/doclist.js",
"lib/public/js/wn/app.js"
]
},
@@ -98,6 +93,13 @@
"lib/public/js/lib/tiny_mce_3.5.7/jquery.tinymce.js:concat",
"lib/public/js/lib/mousetrap.min.js",
"lib/public/js/wn/router.js",
"lib/public/js/wn/model/model.js",
"lib/public/js/wn/model/doclist.js",
"lib/public/js/wn/model/sync.js",
"lib/public/js/wn/model/create_new.js",
"lib/public/js/wn/model/perm.js",

"lib/public/js/wn/misc/tools.js",
"lib/public/js/legacy/utils/printElement.js",
"lib/public/js/legacy/widgets/form/fields.js",


+ 2
- 2
public/js/legacy/globals.js View File

@@ -10,6 +10,8 @@ wn.provide('_r');
wn.provide('_c');
wn.provide('_e');
wn.provide('_startup_data')
wn.provide('locals')
wn.provide('locals.DocType')

// setup custom binding for history
wn.settings.no_history = 1;
@@ -52,6 +54,4 @@ var FILTER_SEP = '\1';
var frms={};
var cur_frm=null;
var pscript = {};
var validated = true;
var validation_message = '';
var tinymce_loaded = null;

+ 0
- 175
public/js/legacy/model/doclist.js View File

@@ -1,175 +0,0 @@
// Copyright (c) 2012 Web Notes Technologies Pvt Ltd (http://erpnext.com)
//
// MIT License (MIT)
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
// OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//

function compress_doclist(list) {
var kl = {}; var vl = []; var flx = {};
for(var i=0; i<list.length;i++) {
var o = list[i];
var fl = [];
if(!kl[o.doctype]) { // make key only once # doctype must be first
var tfl = ['doctype', 'name', 'docstatus', 'owner', 'parent', 'parentfield', 'parenttype',
'idx', 'creation', 'modified', 'modified_by', '__islocal', '__newname', '__modified',
'_user_tags', '__temp'];
var fl = [].concat(tfl);
for(key in wn.meta.docfield_map[o.doctype]) { // all other values
if(!in_list(fl, key)
&& !in_list(no_value_fields, wn.meta.docfield_map[o.doctype][key].fieldtype)
&& !wn.meta.docfield_map[o.doctype][key].no_column) {
fl[fl.length] = key; // save value list
tfl[tfl.length] = key //.replace(/'/g, "\\'").replace(/\n/g, "\\n");
}
}
flx[o.doctype] = fl;
kl[o.doctype] = tfl
}
var nl = [];
var fl = flx[o.doctype];
// check all
for(var j=0;j<fl.length;j++) {
var v = o[fl[j]];
nl.push(v);
}
vl.push(nl);
}
return JSON.stringify({'_vl':vl, '_kl':kl});
}

function expand_doclist(docs) {
var l = [];
for(var i=0;i<docs._vl.length;i++)
l[l.length] = zip(docs._kl[docs._vl[i][0]], docs._vl[i]);
return l;
}
function zip(k,v) {
var obj = {};
for(var i=0;i<k.length;i++) {
obj[k[i]] = v[i];
}
return obj;
}

function save_doclist(dt, dn, save_action, onsave, onerr, btn) {
var doc = locals[dt][dn];
var doctype = locals['DocType'][dt];
var tmplist = [];
// make doc list
var doclist = make_doclist(dt, dn, 1);
var all_reqd_ok = true;
if(save_action!='Cancel') {
for(var n in doclist) {
// type / mandatory checking
var reqd_ok = check_required(doclist[n].doctype, doclist[n].name, doclist[0].doctype);
if(doclist[n].docstatus+''!='2' && all_reqd_ok) // if not deleted
all_reqd_ok = reqd_ok;
}
}
// mandatory not filled
if(!all_reqd_ok) {
onerr()
return;
}
var _save = function() {
//console.log(compress_doclist(doclist));
btn && $(btn).attr("disabled", true);
$c('webnotes.widgets.form.save.savedocs', {'docs':compress_doclist(doclist), 'docname':dn, 'action': save_action, 'user':user },
function(r) {
btn && $(btn).attr("disabled", false);
if(r.saved) {
if(onsave)onsave(r);
} else {
if(onerr)onerr(r);
}
}, function() {
//
},0,(f ? 'Saving...' : '')
);
}

// ask for name
if(doc.__islocal && (doctype && doctype.autoname && doctype.autoname.toLowerCase()=='prompt')) {
var newname = prompt('Enter the name of the new '+ dt, '');
if(newname) {
doc.__newname = strip(newname); _save();
} else {
msgprint('Not Saved'); onerr();
}
} else {
_save();
}
}

function check_required(dt, dn, parent_dt) {
var doc = locals[dt][dn];
if(doc.docstatus>1)return true;
var fl = wn.meta.docfield_list[dt];
if(!fl)return true; // no doctype loaded
var all_clear = true;
var errfld = [];
for(var i=0;i<fl.length;i++) {
var key = fl[i].fieldname;
var df = wn.meta.get_docfield(dt, key, dn);
var has_value = wn.model.has_value(dt, dn, key);

if(df.reqd && !has_value) {
errfld[errfld.length] = df.label;
// Bring to front "Section"
if(cur_frm) {
// show as red
var f = cur_frm.fields_dict[df.fieldname];
if(f) {
// in form
f.df.has_error = true;
f.refresh_label_icon && f.refresh_label_icon();
if(all_clear && f.wrapper) {
$(document).scrollTop($(f.wrapper).offset().top - 100);
}
if(f.df.hidden) {
msgprint('Oops, field "'+ f.df.label+'" is both hidden and mandatory. \
Please contact your admin for help.');
}
}
}
if(all_clear)all_clear = false;
}
}
if(errfld.length)msgprint('<b>Mandatory fields required in '+
(doc.parenttype ? (wn.meta.docfield_map[doc.parenttype][doc.parentfield].label + ' (Table)') :
doc.doctype) + ':</b>\n' + errfld.join('\n'));
return all_clear;
}

+ 0
- 288
public/js/legacy/model/local_data.js View File

@@ -1,288 +0,0 @@
// Copyright (c) 2012 Web Notes Technologies Pvt Ltd (http://erpnext.com)
//
// MIT License (MIT)
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
// OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//

// Local DB
//-----------

var locals = {'DocType':{}};
var LocalDB={};
var READ = 0; var WRITE = 1; var CREATE = 2; var SUBMIT = 3; var CANCEL = 4; var AMEND = 5;

LocalDB.getchildren = function(child_dt, parent, parentfield, parenttype) {
var l = [];
for(var key in locals[child_dt]) {
var d = locals[child_dt][key];
if((d.parent == parent)&&(d.parentfield == parentfield)) {
if(parenttype) {
if(d.parenttype==parenttype)l.push(d);
} else { // ignore for now
l.push(d);
}
}
}
l.sort(function(a,b){return (cint(a.idx)-cint(b.idx))}); return l;
}

// Add Doc
// ======================================================================================

LocalDB.add=function(dt, dn) {
if(!locals[dt]) locals[dt] = {}; if(locals[dt][dn]) delete locals[dt][dn];
locals[dt][dn] = {'name':dn, 'doctype':dt, 'docstatus':0};
return locals[dt][dn];
}

// Delete Doc
// ======================================================================================

LocalDB.delete_doc=function(dt, dn) {
var doc = get_local(dt, dn);
if(!doc) return;

for(var ndt in locals) { // all doctypes
if(locals[ndt]) {
for(var ndn in locals[ndt]) {
var doc = locals[ndt][ndn];
if(doc && doc.parenttype==dt && (doc.parent==dn||doc.__oldparent==dn)) {
delete locals[ndt][ndn];
}
}
}
}
delete locals[dt][dn];
}

function get_local(dt, dn) { return locals[dt] ? locals[dt][dn] : null; }

// Sync Records from Server
// ======================================================================================

LocalDB.sync = function(list) {
if(keys(list._kl))
list = expand_doclist(list);
if(list.length) {
LocalDB.clear_locals(list[0].doctype, list[0].name);
} else {
return;
}
for(var i=0;i<list.length;i++) {
var d = list[i];
if(!d.name) // get name (local if required)
d.name = LocalDB.get_localname(d.doctype);

LocalDB.add(d.doctype, d.name);
locals[d.doctype][d.name] = d;

// reset cur_frm.doc (as new doc is loaded from the server)
if(cur_frm && cur_frm.doctype==d.doctype && cur_frm.docname==d.name) {
cur_frm.doc = d;
}

if(d.doctype=='DocField')
wn.meta.add_field(d);

if(d.localname) {
wn.model.new_names[d.localname] = d.name;
$(document).trigger('rename', [d.doctype, d.localname, d.name]);
delete locals[d.doctype][d.localname];
}
}
}

LocalDB.clear_locals = function(dt, dn) {
var doclist = make_doclist(dt, dn, 1);
// console.dir(['in clear', doclist]);
$.each(doclist, function(i, v) {
v && delete locals[v.doctype][v.name];
});
}


// Get Local Name
// ======================================================================================

local_name_idx = {};
LocalDB.get_localname=function(doctype) {
if(!local_name_idx[doctype]) local_name_idx[doctype] = 1;
var n = 'New '+ get_doctype_label(doctype) + ' ' + local_name_idx[doctype];
local_name_idx[doctype]++;
return n;
}

// Create Local Doc
// ======================================================================================

LocalDB.set_default_values = function(doc) {
var doctype = doc.doctype;
var docfields = wn.meta.docfield_list[doctype];
if(!docfields) {
return;
}
var fields_to_refresh = [];
for(var fid=0;fid<docfields.length;fid++) {
var f = docfields[fid];
if(!in_list(no_value_fields, f.fieldtype) && doc[f.fieldname]==null) {
var v = LocalDB.get_default_value(f.fieldname, f.fieldtype, f['default']);
if(v) {
doc[f.fieldname] = v;
fields_to_refresh.push(f.fieldname);
}
}
}
return fields_to_refresh;
}

// ======================================================================================

LocalDB.create = function(doctype, n) {
if(!n) n = LocalDB.get_localname(doctype);
var doc = LocalDB.add(doctype, n)
doc.__islocal=1; doc.owner = user;
LocalDB.set_default_values(doc);
return n;
}

// ======================================================================================

LocalDB.delete_record = function(dt, dn) {
delete locals[dt][dn];
}

// ======================================================================================

LocalDB.get_default_value = function(fn, ft, df) {
if(df=='_Login' || df=='__user')
return user;
else if(df=='_Full Name')
return user_fullname;
else if(ft=='Date'&& (df=='Today' || df=='__today')) {
return get_today(); }
else if(df)
return df;
else if(user_defaults[fn])
return user_defaults[fn][0];
else if(sys_defaults[fn])
return sys_defaults[fn];
}

// ======================================================================================

LocalDB.add_child = function(doc, childtype, parentfield) {
// create row doc
var n = LocalDB.create(childtype);
var d = locals[childtype][n];
d.parent = doc.name;
d.parentfield = parentfield;
d.parenttype = doc.doctype;
return d;
}

// ======================================================================================

LocalDB.no_copy_list = ['amended_from','amendment_date','cancel_reason'];
LocalDB.copy=function(dt, dn, from_amend) {
var newdoc = LocalDB.create(dt);
for(var key in locals[dt][dn]) {
// dont copy name and blank fields
var df = wn.meta.get_docfield(dt, key);
if(key!=='name' && key.substr(0,2)!='__' &&
!(df && ((!from_amend && cint(df.no_copy)==1) || in_list(LocalDB.no_copy_list, df.fieldname)))) {
locals[dt][newdoc][key] = locals[dt][dn][key];
}
}
return locals[dt][newdoc];
}

// ======================================================================================

function make_doclist(dt, dn) {
if(!locals[dt]) { return []; }
var dl = [];
dl[0] = locals[dt][dn];
// get children
for(var ndt in locals) { // all doctypes
if(locals[ndt]) {
for(var ndn in locals[ndt]) {
var doc = locals[ndt][ndn];
if(doc && doc.parenttype==dt && doc.parent==dn) {
dl.push(doc)
}
}
}
}
return dl;
}

// Meta Data
// ======================================================================================

var Meta={};
var local_dt = {};

// Make Unique Copy of DocType for each record for client scripting
Meta.make_local_dt = function(dt, dn) {
var dl = make_doclist('DocType', dt);
if(!local_dt[dt]) local_dt[dt]={};
if(!local_dt[dt][dn]) local_dt[dt][dn]={};
for(var i=0;i<dl.length;i++) {
var d = dl[i];
if(d.doctype=='DocField') {
var key = d.fieldname ? d.fieldname : d.label;
local_dt[dt][dn][key] = copy_dict(d);
local_dt[dt][dn][key].__copy = true;
}
}
}

Meta.set_field_property=function(fn, key, val, doc) {
if(!doc && (cur_frm.doc))doc = cur_frm.doc;
try{
local_dt[doc.doctype][doc.name][fn][key] = val;
refresh_field(fn);
} catch(e) {
alert("Client Script Error: Unknown values for " + doc.name + ',' + fn +'.'+ key +'='+ val);
}
}

Meta.get_field = function(dt, fn, dn) {
try {
return local_dt[dt][dn][fn];
} catch(e) {
return null;
}
}

// Get Dt label
// ======================================================================================
function get_doctype_label(dt) {
return dt
}

function get_label_doctype(label) {
return label
}
// Global methods for API
// ======================================================================================

var getchildren = LocalDB.getchildren;
var createLocal = LocalDB.create;

+ 2
- 2
public/js/legacy/utils/handler.js View File

@@ -44,7 +44,7 @@ function $c_obj(doclist, method, arg, callback, no_spinner, freeze_msg, btn) {
if(typeof doclist=='string')
args.doctype = doclist;
else
args.docs = compress_doclist(doclist)
args.docs = wn.model.compress(doclist)
wn.request.call({
args: args,
@@ -84,7 +84,7 @@ function $c_obj_csv(doclist, method, arg) {
if(doclist.substr)
args.doctype = doclist;
else
args.docs = compress_doclist(doclist);
args.docs = wn.model.compress(doclist);

// open
open_url_post(wn.request.url, args);


+ 1
- 3
public/js/legacy/webpage/loaders.js View File

@@ -28,7 +28,6 @@ function loadreport(dt, rep_name, onload) {
}

function loaddoc(doctype, name, onload) {
//doctype = get_label_doctype(doctype);
wn.model.with_doctype(doctype, function() {
if(locals.DocType[doctype].in_dialog) {
_f.edit_record(doctype, name);
@@ -40,10 +39,9 @@ function loaddoc(doctype, name, onload) {
var load_doc = loaddoc;

function new_doc(doctype, in_form) {
doctype = get_label_doctype(doctype);
wn.model.with_doctype(doctype, function() {
if(!in_form && locals.DocType[doctype].in_dialog) {
var new_name = LocalDB.create(doctype);
var new_name = wn.model.make_new_doc_and_get_name(doctype);
_f.edit_record(doctype, new_name);
} else {
wn.views.formview.create(doctype);


+ 1
- 1
public/js/legacy/webpage/search.js View File

@@ -74,7 +74,7 @@ function makeselector() {
}
d.style = 'Search';
if(d.input) { d.input = null; sel_type = null; }
d.sel_type = get_label_doctype(dt);
d.sel_type = dt;
d.set_title('Quick Search for ' + dt);
}



+ 2
- 2
public/js/legacy/widgets/form/clientscriptAPI.js View File

@@ -44,7 +44,7 @@ get_server_fields = function(method, arg, table_field, doc, dt, dn, allow_edit,
if(!allow_edit) wn.dom.freeze();
$c('runserverobj',
args={'method':method,
'docs':compress_doclist(make_doclist(doc.doctype, doc.name)),
'docs':wn.model.compress(make_doclist(doc.doctype, doc.name)),
'arg':arg
},
function(r, rt) {
@@ -127,7 +127,7 @@ set_field_permlevel = function(n, level) {
}

toggle_field = function(n, hidden) {
var df = Meta.get_field(cur_frm.doctype, n, cur_frm.docname);
var df = wn.meta.get_docfield(cur_frm.doctype, n, cur_frm.docname);
if(df) {
df.hidden = hidden;
refresh_field(n);


+ 2
- 2
public/js/legacy/widgets/form/fields.js View File

@@ -759,8 +759,8 @@ LinkField.prototype.validate_link = function(val, from_selector) {
me.run_trigger();
} else {
var astr = '';
if(in_list(profile.can_create, me.df.options)) astr = repl('<br><br><span class="link_type" onclick="newdoc(\'%(dt)s\')">Click here</span> to create a new %(dtl)s', {dt:me.df.options, dtl:get_doctype_label(me.df.options)})
msgprint(repl('error:<b>%(val)s</b> is not a valid %(dt)s.<br><br>You must first create a new %(dt)s <b>%(val)s</b> and then select its value. To find an existing %(dt)s, click on the magnifying glass next to the field.%(add)s', {val:me.txt.value, dt:get_doctype_label(me.df.options), add:astr}));
if(in_list(profile.can_create, me.df.options)) astr = repl('<br><br><span class="link_type" onclick="newdoc(\'%(dt)s\')">Click here</span> to create a new %(dtl)s', {dt:me.df.options, dtl:wn._(me.df.options)})
msgprint(repl('error:<b>%(val)s</b> is not a valid %(dt)s.<br><br>You must first create a new %(dt)s <b>%(val)s</b> and then select its value. To find an existing %(dt)s, click on the magnifying glass next to the field.%(add)s', {val:me.txt.value, dt:wn._(me.df.options), add:astr}));
me.txt.value = '';
me.set('');
}


+ 52
- 133
public/js/legacy/widgets/form/form.js View File

@@ -46,6 +46,7 @@ _f.Frm = function(doctype, parent, in_form) {
this.docname = '';
this.doctype = doctype;
this.display = 0;
this.refresh_if_stale_for = 600;
var me = this;
this.is_editable = {};
@@ -215,7 +216,7 @@ _f.Frm.prototype.print_doc = function() {
_f.Frm.prototype.email_doc = function(message) {
new wn.views.CommunicationComposer({
doc: this.doc,
subject: get_doctype_label(this.meta.name) + ': ' + this.docname,
subject: wn._(this.meta.name) + ': ' + this.docname,
recipients: this.doc.email || this.doc.email_id || this.doc.contact_email,
attach_document_print: true,
message: message,
@@ -237,7 +238,7 @@ _f.Frm.prototype.rename_notify = function(dt, old, name) {
if(this.docname == old)
this.docname = name;
else
return; // thats it, not for children!
return;

// editable
this.is_editable[name] = this.is_editable[old];
@@ -245,9 +246,9 @@ _f.Frm.prototype.rename_notify = function(dt, old, name) {

// cleanup
if(this && this.opendocs[old]) {
// local doctype copy
local_dt[dt][name] = local_dt[dt][old];
local_dt[dt][old] = null;
// delete docfield copy
wn.meta.docfield_copy[dt][name] = wn.meta.docfield_copy[dt][old];
delete wn.meta.docfield_copy[dt][old];
}

delete this.opendocs[old];
@@ -260,19 +261,16 @@ _f.Frm.prototype.rename_notify = function(dt, old, name) {
// SETUP

_f.Frm.prototype.setup_meta = function(doctype) {
this.meta = get_local('DocType',this.doctype);
this.meta = wn.model.get_doc('DocType',this.doctype);
this.perm = wn.perm.get_perm(this.doctype); // for create
if(this.meta.istable) { this.meta.in_dialog = 1 }
this.setup_print();
}



_f.Frm.prototype.setup_sidebar = function() {
this.sidebar = new wn.widgets.form.sidebar.Sidebar(this);
}


_f.Frm.prototype.setup_footer = function() {
var me = this;
@@ -372,7 +370,6 @@ _f.Frm.prototype.setup_fields_std = function() {
}
}

// --------------------------------------------------------------------------------------
_f.Frm.prototype.add_custom_button = function(label, fn, icon) {
this.frm_head.appframe.add_button(label, fn, icon);
}
@@ -380,8 +377,6 @@ _f.Frm.prototype.clear_custom_buttons = function() {
this.frm_head.refresh_toolbar()
}

// --------------------------------------------------------------------------------------

_f.Frm.prototype.add_fetch = function(link_field, src_field, tar_field) {
if(!this.fetch_dict[link_field]) {
this.fetch_dict[link_field] = {'columns':[], 'fields':[]}
@@ -390,8 +385,6 @@ _f.Frm.prototype.add_fetch = function(link_field, src_field, tar_field) {
this.fetch_dict[link_field].fields.push(tar_field);
}

// --------------------------------------------------------------------------------------

_f.Frm.prototype.setup_client_script = function() {
// setup client obj

@@ -400,8 +393,6 @@ _f.Frm.prototype.setup_client_script = function() {
}
}

// --------------------------------------------------------------------------------------

_f.Frm.prototype.refresh_print_layout = function() {
$ds(this.print_wrapper);
$dh(this.page_layout.wrapper);
@@ -432,8 +423,6 @@ _f.Frm.prototype.refresh_print_layout = function() {
}


// --------------------------------------------------------------------------------------

_f.Frm.prototype.show_the_frm = function() {
// show the dialog
if(this.meta.in_dialog && !this.parent.dialog.display) {
@@ -443,38 +432,15 @@ _f.Frm.prototype.show_the_frm = function() {
}
}

// --------------------------------------------------------------------------------------
_f.Frm.prototype.set_print_heading = function(txt) {
this.pformat[cur_frm.docname] = txt;
}

// --------------------------------------------------------------------------------------

_f.Frm.prototype.defocus_rest = function() {
// deselect others
if(_f.cur_grid_cell) _f.cur_grid_cell.grid.cell_deselect();
}

// -------- Permissions -------
// Returns global permissions, at all levels
// ======================================================================================

_f.Frm.prototype.get_doc_perms = function() {
var p = [0,0,0,0,0,0];
for(var i=0; i<this.perm.length; i++) {
if(this.perm[i]) {
if(this.perm[i][READ]) p[READ] = 1;
if(this.perm[i][WRITE]) p[WRITE] = 1;
if(this.perm[i][SUBMIT]) p[SUBMIT] = 1;
if(this.perm[i][CANCEL]) p[CANCEL] = 1;
if(this.perm[i][AMEND]) p[AMEND] = 1;
}
}
return p;
}

// refresh
// ======================================================================================
_f.Frm.prototype.refresh_header = function() {
// set title
// main title
@@ -493,8 +459,6 @@ _f.Frm.prototype.refresh_header = function() {
wn.ui.toolbar.recent.add(this.doctype, this.docname, 1);
}

// --------------------------------------------------------------------------------------

_f.Frm.prototype.check_doc_perm = function() {
// get perm
var dt = this.parent_doctype?this.parent_doctype : this.doctype;
@@ -516,8 +480,6 @@ _f.Frm.prototype.check_doc_perm = function() {
return 1
}

// --------------------------------------------------------------------------------------

_f.Frm.prototype.refresh = function(docname) {
// record switch
if(docname) {
@@ -535,15 +497,20 @@ _f.Frm.prototype.refresh = function(docname) {

// check permissions
if(!this.check_doc_perm()) return;

// set the doc
this.doc = wn.model.get_doc(this.doctype, this.docname);
// check if doctype is already open
if (!this.opendocs[this.docname]) {
this.check_doctype_conflict(this.docname);
} else {
if((new Date() - this.doc.__last_sync_on) / 1000 > this.refresh_if_stale_for) {
this.reload_doc();
return;
}
}

// set the doc
this.doc = get_local(this.doctype, this.docname);

// do setup
if(!this.setup_done) this.setup();

@@ -621,13 +588,11 @@ _f.Frm.prototype.refresh = function(docname) {
}
}

// --------------------------------------------------------------------------------------

_f.Frm.prototype.refresh_footer = function() {
var f = this.page_layout.footer;
if(f.save_area) {
if(this.editable && (!this.meta.in_dialog || this.in_form)
&& this.doc.docstatus==0 && !this.meta.istable && this.get_doc_perms()[WRITE]
&& this.doc.docstatus==0 && !this.meta.istable && this.perm[0][WRITE]
&& (this.fields && this.fields.length > 7)) {
f.show_save();
} else {
@@ -755,18 +720,14 @@ _f.Frm.prototype.setnewdoc = function(docname) {
return;
}

//if(!this.meta)
// this.setup_meta();

// make a copy of the doctype for client script settings
// each record will have its own client script
Meta.make_local_dt(this.doctype,docname);
wn.meta.make_docfield_copy_for(this.doctype,docname);

this.docname = docname;

var me = this;
var viewname = docname;
if(this.meta.issingle) viewname = this.doctype;
var viewname = this.meta.issingle ? this.doctype : docname;

// Client Script
this.runclientscript('onload', this.doctype, this.docname);
@@ -788,82 +749,12 @@ _f.Frm.prototype.show_doc = function(dn) {
this.refresh(dn);
}

// ======================================================================================
var validated; // bad design :(
_f.Frm.prototype.save = function(save_action, callback, btn) {
// removes focus from a field before save,
// so that its change event gets triggered before saving
$(document.activeElement).blur();
//alert(save_action);
if(!save_action) {
if(cint(this.doc.docstatus) > 0) return;
save_action = 'Save';
}

if(save_action=='Submit') {
locals[this.doctype][this.docname].submitted_on = dateutil.full_str();
locals[this.doctype][this.docname].submitted_by = user;
}
if(save_action=='Trash') {
var reason = prompt('Reason for trash (mandatory)', '');
if(!strip(reason)) {
msgprint('Reason is mandatory, not trashed');
return;
}
locals[this.doctype][this.docname].trash_reason = reason;
}

// run validations
if(save_action=='Cancel') {
var reason = prompt('Reason for cancellation (mandatory)', '');
if(!strip(reason)) {
msgprint('Reason is mandatory, not cancelled');
return;
}
locals[this.doctype][this.docname].cancel_reason = reason;
locals[this.doctype][this.docname].cancelled_on = dateutil.full_str();
locals[this.doctype][this.docname].cancelled_by = user;
} else if(save_action=='Update') {
// no validation for update
} else { // no validation for cancellation
validated = true;
if(this.cscript.validate)
this.runclientscript('validate');
if(!validated) {
return 'Error';
}
}
var onsave = function(r) {
if(!me.meta.istable && r) {
me.refresh(r.docname);
}
callback && callback(r)
}

var me = this;
var onerr = function(r) {
var doc = locals[me.doctype][me.docname];
onsave(r);
}
if(this.docname && validated) {
// scroll to top
scroll(0, 0);
return save_doclist(this.doctype, this.docname, save_action, onsave, onerr, btn);
}
}


_f.Frm.prototype.runscript = function(scriptname, callingfield, onrefresh) {
var me = this;
if(this.docname) {
// make doc list
var doclist = compress_doclist(make_doclist(this.doctype, this.docname));
var doclist = wn.model.compress(make_doclist(this.doctype, this.docname));
// send to run
if(callingfield)
$(callingfield.input).set_working();
@@ -906,7 +797,7 @@ _f.Frm.prototype.runclientscript = function(caller, cdt, cdn) {

if(caller && caller.toLowerCase()=='setup') {

var doctype = get_local('DocType', this.doctype);
var doctype = wn.model.get_doc('DocType', this.doctype);
// js
var cs = doctype.__js || (doctype.client_script_core + doctype.client_script);
@@ -941,7 +832,7 @@ _f.Frm.prototype.copy_doc = function(onload, from_amend) {
var dn = this.docname;
// copy parent
var newdoc = LocalDB.copy(this.doctype, dn, from_amend);
var newdoc = wn.model.copy_doc(this.doctype, dn, from_amend);

// do not copy attachments
if(this.meta.allow_attach && newdoc.file_list && !from_amend)
@@ -962,7 +853,7 @@ _f.Frm.prototype.copy_doc = function(onload, from_amend) {
}
if(d1.parent==dn && cint(tf_dict[d1.parentfield].no_copy)!=1) {
var ch = LocalDB.copy(d1.doctype, d1.name, from_amend);
var ch = wn.model.copy_doc(d1.doctype, d1.name, from_amend);
ch.parent = newdoc.name;
ch.docstatus = 0;
ch.owner = user;
@@ -1003,6 +894,31 @@ _f.Frm.prototype.reload_doc = function() {
}
}

var validated;
_f.Frm.prototype.save = function(save_action, callback, btn) {
$(document.activeElement).blur();
var me = this;
var doclist = new wn.model.DocList(this.doctype, this.docname);
// validate
if(save_action!="Cancel") {
validated = true;
if(this.cscript.validate)
this.runclientscript('validate');
if(!validated) {
return;
}
}
doclist.save(save_action || "Save", function(r) {
if(!r.exc) {
me.refresh();
}
callback && callback(r);
}, btn);
}


_f.Frm.prototype.savesubmit = function(btn) {
var me = this;
wn.confirm("Permanently Submit "+this.docname+"?", function() {
@@ -1017,7 +933,10 @@ _f.Frm.prototype.savesubmit = function(btn) {
_f.Frm.prototype.savecancel = function(btn) {
var me = this;
wn.confirm("Permanently Cancel "+this.docname+"?", function() {
me.save('Cancel', null, btn);
var doclist = new wn.model.DocList(me.doctype, me.docname);
doclist.cancel(function(r) {
if(!r.exc) me.refresh();
}, btn);
});
}



+ 3
- 3
public/js/legacy/widgets/form/form_grid.js View File

@@ -158,7 +158,7 @@ _f.FormGrid.prototype.insert_row = function() {

_f.FormGrid.prototype.new_row_doc = function() {
// create row doc
var n = LocalDB.create(this.doctype);
var n = wn.model.make_new_doc_and_get_name(this.doctype);
var d = locals[this.doctype][n];
d.parent = this.field.frm.docname;
d.parentfield = this.field.df.fieldname;
@@ -220,7 +220,7 @@ _f.FormGrid.prototype.check_selected = function() {

_f.FormGrid.prototype.delete_row = function(dt, dn) {
if(dt && dn) {
LocalDB.delete_record(dt, dn);
wn.model.clear_doc(dt, dn);
this.refresh();
} else {
if(!this.check_selected()) return;
@@ -230,7 +230,7 @@ _f.FormGrid.prototype.delete_row = function(dt, dn) {
var ci = _f.cur_grid_cell.cellIndex;
var ri = _f.cur_grid_cell.row.rowIndex;
LocalDB.delete_record(this.doctype, r.docname);
wn.model.clear_doc(this.doctype, r.docname);
this.refresh();
if(ri < (this.tab.rows.length-1))


+ 2
- 2
public/js/legacy/widgets/form/form_header.js View File

@@ -80,7 +80,7 @@ _f.FrmHeader = Class.extend({
this.$w.find('.avatar img').centerImage();
},
refresh_labels: function() {
cur_frm.doc = get_local(cur_frm.doc.doctype, cur_frm.doc.name);
cur_frm.doc = wn.model.get_doc(cur_frm.doc.doctype, cur_frm.doc.name);
var labinfo = {
0: ['Saved', 'label-success'],
1: ['Submitted', 'label-info'],
@@ -121,7 +121,7 @@ _f.FrmHeader = Class.extend({
}
this.appframe.clear_buttons();
var p = cur_frm.get_doc_perms();
var p = cur_frm.perm[0];

// Edit
if(cur_frm.meta.read_only_onload && !cur_frm.doc.__islocal) {


+ 1
- 1
public/js/legacy/widgets/form/print_format.js View File

@@ -452,7 +452,7 @@ $.extend(_p, {
}
}
// if not, just have doctype has heading
h1.innerHTML = val ? val : get_doctype_label(doctype);
h1.innerHTML = val ? val : wn._(doctype);
}
var h2_style = {


+ 9
- 14
public/js/legacy/widgets/report_builder/report_builder.js View File

@@ -132,7 +132,7 @@ _r.ReportBuilder = function(parent, doctype, onload) {
$ds(me.wrapper);
// reset main title
this.set_main_title('Report: ' + get_doctype_label(me.doctype));
this.set_main_title('Report: ' + wn._(me.doctype));
if(my_onload)my_onload(me);
}
@@ -156,7 +156,7 @@ _r.ReportBuilder.prototype.make_tabs = function() {

_r.ReportBuilder.prototype.make_body = function() {

this.set_main_title('Report: ' + get_doctype_label(this.doctype));
this.set_main_title('Report: ' + wn._(this.doctype));
var me = this;

this.make_save_criteria();
@@ -204,7 +204,7 @@ _r.ReportBuilder.prototype.save_criteria = function(save_as) {
if(!criteria_name)
return;
var dn = createLocal('Search Criteria');
var dn = wn.model.make_new_doc_and_get_name('Search Criteria');
var doc = locals['Search Criteria'][dn];

doc.criteria_name = criteria_name;
@@ -243,12 +243,7 @@ _r.ReportBuilder.prototype.save_criteria = function(save_as) {
me.sc_dict[criteria_name] = r.main_doc_name;
me.set_criteria_sel(criteria_name);
}
//if(this.current_loaded && overwrite) {
// msgprint('Filters and Columns Synchronized. You must also "Save" the Search Criteria to update');
// loaddoc('Search Criteria', this.sc_dict[this.current_loaded]);
//} else {
save_doclist(doc.doctype, doc.name, 'Save', fn); // server-side save
//}
new wn.model.DocList(doc.doctype, doc.name).save("Save", fn);
}

// -------------------------------------------------------------------------------------
@@ -292,7 +287,7 @@ _r.ReportBuilder.prototype.clear_criteria = function() {
this.set_sort_options();
this.set_main_title('Report: ' + get_doctype_label(this.doctype));
this.set_main_title('Report: ' + wn._(this.doctype));

this.current_loaded = null;
this.customized_filters = null;
@@ -503,10 +498,10 @@ _r.ReportBuilder.prototype.setup_dt_filters_and_cols = function(fl, dt) {

// set section headings
var lab = $a(me.filter_area,'div','filter_dt_head');
lab.innerHTML = 'Filters for ' + get_doctype_label(dt);
lab.innerHTML = 'Filters for ' + wn._(dt);

var lab = $a(me.picker_area,'div','builder_dt_head');
lab.innerHTML = 'Select columns for ' + get_doctype_label(dt);
lab.innerHTML = 'Select columns for ' + wn._(dt);

// get fields
var dt_fields = wn.meta.docfield_list[dt];
@@ -678,7 +673,7 @@ _r.ReportBuilder.prototype.make_datatable = function() {
// get search criteria
if(me.current_loaded && me.sc_dict[me.current_loaded]) {
var sc = get_local('Search Criteria', me.sc_dict[me.current_loaded]);
var sc = wn.model.get_doc('Search Criteria', me.sc_dict[me.current_loaded]);
}
if(sc) me.dt.search_criteria = sc;
@@ -1221,7 +1216,7 @@ _r.ReportColumnPicker.prototype.set_options = function(s, l) {

for(var i=0; i<l.length; i++) {
var v = l[i].df.parent + '.' + l[i].df.label;
var v_label = get_doctype_label(l[i].df.parent) + '.' + l[i].df.label;
var v_label = wn._(l[i].df.parent) + '.' + l[i].df.label;
var o = new Option (v_label, v, false, false);
o.field = l[i];
if(o.field.is_selected) o.selected = 1;


+ 2
- 1
public/js/legacy/wn/widgets/form/comments.js View File

@@ -36,7 +36,8 @@ wn.widgets.form.sidebar.Comments = function(parent, sidebar, doctype, docname) {
this.refresh_latest_comment = function() {
var wrapper = cur_frm.page_layout.body;
if(!$(wrapper).find(".latest-comment").length) {
$('<div class="latest-comment alert alert-info" style="margin-top:20px;">').prependTo(wrapper);
$('<div class="latest-comment alert alert-info" style="margin-top:20px; display: none;">')
.prependTo(wrapper);
}
var comment_list = wn.widgets.form.comments.comment_list[me.docname];
if(comment_list) {


+ 22
- 2
public/js/wn/meta.js View File

@@ -21,6 +21,7 @@
//

wn.provide('wn.meta.docfield_map');
wn.provide('wn.meta.docfield_copy');
wn.provide('wn.meta.docfield_list');
wn.provide('wn.meta.doctypes');
wn.provide("wn.meta.precision_map");
@@ -43,9 +44,21 @@ $.extend(wn.meta, {
wn.meta.docfield_list[df.parent].push(df);
},
make_docfield_copy_for: function(doctype, docname) {
var c = wn.meta.docfield_copy;
if(!c[doctype])
c[doctype] = {};
if(!c[doctype][docname])
c[doctype][docname] = {};
$.each(wn.meta.docfield_list[doctype], function(i, df) {
c[doctype][docname][df.fieldname || df.label] = copy_dict(df);
})
},
get_docfield: function(dt, fn, dn) {
if(dn && local_dt[dt] && local_dt[dt][dn]){
return local_dt[dt][dn][fn];
if(dn && wn.meta.docfield_copy[dt] && wn.meta.docfield_copy[dt][dn]){
return wn.meta.docfield_copy[dt][dn][fn];
} else {
return wn.meta.docfield_map[dt][fn];
}
@@ -85,4 +98,11 @@ $.extend(wn.meta, {
return wn.meta.precision_map[doctype];
},

sync_messages: function(doc) {
if(doc.__messages) {
$.extend(wn._messages, doc.__messages);
}
},
});

+ 99
- 0
public/js/wn/model/create_new.js View File

@@ -0,0 +1,99 @@
wn.provide("wn.model");

$.extend(wn.model, {
new_names: {},
new_name_count: {},

get_new_doc: function(doctype) {
wn.provide("locals." + doctype);
var doc = {
docstatus: 0,
doctype: doctype,
name: wn.model.get_new_name(doctype),
__islocal: 1,
owner: user
};
wn.model.set_default_values(doc);
locals[doctype][doc.name] = doc;
return doc;
},
make_new_doc_and_get_name: function(doctype) {
return wn.model.get_new_doc(doctype).name;
},
get_new_name: function(doctype) {
var cnt = wn.model.new_name_count
if(!cnt[doctype])
cnt[doctype] = 0;
cnt[doctype]++;
return 'New '+ doctype + ' ' + cnt[doctype];
},
set_default_values: function(doc) {
var doctype = doc.doctype;
var docfields = wn.meta.docfield_list[doctype] || [];
var updated = [];
for(var fid=0;fid<docfields.length;fid++) {
var f = docfields[fid];
if(!in_list(no_value_fields, f.fieldtype) && doc[f.fieldname]==null) {
var v = wn.model.get_default_value(f);
if(v) {
doc[f.fieldname] = v;
updated.push(f.fieldname);
}
}
}
return updated;
},
get_default_value: function(df) {
var def_vals = {
"_Login": user,
"__user": user,
"Today": dateutil.get_today(),
"__today": dateutil.get_today(),
"Now": dateutil.get_cur_time()
}
if(def_vals[df["default"]])
return def_vals[df["default"]];
else if(df["default"])
return df["default"];
else if(user_defaults[df.fieldname])
return user_defaults[df.fieldname][0];
else if(sys_defaults[df.fieldname])
return sys_defaults[df.fieldname];
},
add_child: function(doc, childtype, parentfield) {
// create row doc
var d = wn.model.get_new_doc(childtype);
$.extend(d, {
parent: doc.name,
parentfield: parentfield,
parenttype: doc.doctype,
idx: getchildren(childtype, d.parent, d.parentfield, d.parenttype).length
});
return d;
},
copy_doc: function(dt, dn, from_amend) {
var no_copy_list = ['name','amended_from','amendment_date','cancel_reason'];
var newdoc = wn.model.get_new_doc(dt);

for(var key in locals[dt][dn]) {
// dont copy name and blank fields
var df = wn.meta.get_docfield(dt, key);
if(key.substr(0,2)!='__'
&& !in_list(no_copy_list, key)
&& !(df && (!from_amend && cint(df.no_copy)==1))) {
newdoc[key] = locals[dt][dn][key];
}
}
return newdoc;
},
})

+ 129
- 0
public/js/wn/model/doclist.js View File

@@ -0,0 +1,129 @@
// Copyright (c) 2012 Web Notes Technologies Pvt Ltd (http://erpnext.com)
//
// MIT License (MIT)
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
// OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//

wn.provide("wn.model");
wn.model.DocList = Class.extend({
init: function(doctype, name) {
this.doctype = doctype; this.name = name;
this.doclist = wn.model.get_doclist(this.doctype, this.name);
this.doc = this.doclist[0];
},
save: function(action, callback, btn) {
this.check_name();
if(this.check_mandatory()) {
this._call({
method: "webnotes.widgets.form.save.savedocs",
args: { docs: wn.model.compress(this.doclist), action:action},
callback: callback,
btn: btn
});
}
},
cancel: function(callback, btn) {
this._call({
method: "webnotes.widgets.form.save.cancel",
args: { doctype: this.doctype, name: this.name },
callback: callback,
btn: btn
});
},
check_name: function() {
var doc = this.doclist[0];
var doctype = doc.doctype;
if(doc.__islocal && (doctype && doctype.autoname
&& doctype.autoname.toLowerCase()=='prompt')) {
var newname = prompt('Enter the name of the new '+ dt, '');
if(newname) {
doc.__newname = strip(newname);
} else {
msgprint("Name is required.");
throw "name required";
}
}
},
check_mandatory: function() {
var me = this;
var has_errors = false;
this.scroll_set = false;
if(this.doc.docstatus==2) return true; // don't check for cancel
$.each(this.doclist, function(i, doc) {
var error_fields = [];
$.each(wn.meta.docfield_list[doc.doctype], function(i, docfield) {
if(!docfield.fieldname.std_field) {
var df = wn.meta.get_docfield(doc.doctype,
docfield.fieldname, me.doclist[0].name);
if(df.reqd && !wn.model.has_value(doc.doctype, doc.name, df.fieldname)) {
has_errors = true;
error_fields[error_fields.length] = df.label;
// scroll to field
if(!me.scroll_set)
me.scroll_to(doc.parentfield || df.fieldname);
}
}
});
if(error_fields.length)
msgprint('<b>Mandatory fields required in '+ (doc.parenttype
? (wn.meta.docfield_map[doc.parenttype][doc.parentfield].label + ' (Table)')
: doc.doctype) + ':</b>\n' + error_fields.join('\n'));
});
return !has_errors;
},
scroll_to: function(fieldname) {
var f = cur_frm.fields_dict[fieldname];
if(f) {
$(document).scrollTop($(f.wrapper).offset().top - 100);
}
this.scroll_set = true;
},

_call: function(opts) {
// opts = {
// method: "some server method",
// args: {args to be passed},
// callback: callback,
// btn: btn
// }
$(opts.btn).attr("disabled", true);
wn.call({
freeze: true,
method: opts.method,
args: opts.args,
callback: function(r) {
$(opts.btn).attr("disabled", false);
opts.callback && opts.callback(r);
}
})
},
});

public/js/wn/model.js → public/js/wn/model/model.js View File

@@ -22,7 +22,7 @@

wn.provide('wn.model');

wn.model = {
$.extend(wn.model, {
no_value_type: ['Section Break', 'Column Break', 'HTML', 'Table',
'Button', 'Image'],

@@ -85,7 +85,7 @@ wn.model = {
});
}
},
get_server_module_name: function(doctype) {
var dt = wn.model.scrub(doctype)
return wn.model.scrub(locals.DocType[doctype].module)
@@ -136,6 +136,10 @@ wn.model = {
return wn.utils.filter_dict(locals[doctype], filters);
},
get_doc: function(doctype, name) {
return locals[doctype] ? locals[doctype][name] : null;
},
get_doclist: function(doctype, name, filters) {
var doclist = [];
if(!locals[doctype])
@@ -159,6 +163,47 @@ wn.model = {
return doclist;
},

get_children: function(child_dt, parent, parentfield, parenttype) {
if(parenttype) {
var l = wn.model.get(child_dt, {parent:parent,
parentfield:parentfield, parenttype:parenttype});
} else {
var l = wn.model.get(child_dt, {parent:parent,
parentfield:parentfield});
}

l.sort(function(a,b) { return cint(a.idx) - cint(b.idx) });
$.each(l, function(i, v) { v.idx = i+1; }); // for chrome bugs ???
return l;
},

clear_doclist: function(doctype, name) {
$.each(wn.model.get_doclist(doctype, name), function(i, d) {
if(d) wn.model.clear_doc(d.doctype, d.name);
});
},
clear_doc: function(doctype, name) {
delete locals[doctype][name];
},

copy_doc: function(dt, dn, from_amend) {
var no_copy_list = ['name','amended_from','amendment_date','cancel_reason'];
var newdoc = wn.model.get_new_doc(dt);

for(var key in locals[dt][dn]) {
// dont copy name and blank fields
var df = wn.meta.get_docfield(dt, key);
if(key.substr(0,2)!='__'
&& !in_list(no_copy_list, key)
&& !(df && (!from_amend && cint(df.no_copy)==1))) {
newdoc[key] = locals[dt][dn][key];
}
}
return newdoc;
},
delete_doc: function(doctype, docname, callback) {
wn.confirm("Permanently delete "+ docname + "?", function() {
@@ -170,7 +215,7 @@ wn.model = {
},
callback: function(r, rt) {
if(!r.exc) {
LocalDB.delete_doc(doctype, docname);
wn.model.clear_doclist(doctype, docname);
if(wn.ui.toolbar.recent)
wn.ui.toolbar.recent.remove(doctype, docname);
if(callback) callback(r,rt);
@@ -215,4 +260,8 @@ wn.model = {
});
d.show();
}
}
});

// legacy
getchildren = wn.model.get_children
make_doclist = wn.model.get_doclist

public/js/wn/perm.js → public/js/wn/model/perm.js View File


+ 117
- 0
public/js/wn/model/sync.js View File

@@ -0,0 +1,117 @@
// Copyright (c) 2012 Web Notes Technologies Pvt Ltd (http://erpnext.com)
//
// MIT License (MIT)
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
// OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//

$.extend(wn.model, {
sync: function(doclist, sync_in) {
if(!sync_in)
sync_in = locals;
if(doclist._kl)
doclist = wn.model.expand(doclist);
if(doclist && sync_in==locals)
wn.model.clear_doclist(doclist[0].doctype, doclist[0].name)

$.each(doclist, function(i, d) {
if(!d.name) // get name (local if required)
d.name = wn.model.get_new_name(d.doctype);
if(!sync_in[d.doctype])
sync_in[d.doctype] = {};

sync_in[d.doctype][d.name] = d;
d.__last_sync_on = new Date();
if(cur_frm && cur_frm.doctype==d.doctype && cur_frm.docname==d.name) {
cur_frm.doc = d;
}

if(d.doctype=='DocField') wn.meta.add_field(d);
if(d.doctype=='DocType') wn.meta.sync_messages(d);
if(d.localname) {
wn.model.new_names[d.localname] = d.name;
$(document).trigger('rename', [d.doctype, d.localname, d.name]);
delete sync_in[d.doctype][d.localname];
}
});
},
expand: function(data) {
function zip(k,v) {
var obj = {};
for(var i=0;i<k.length;i++) {
obj[k[i]] = v[i];
}
return obj;
}

var l = [];
for(var i=0;i<data._vl.length;i++) {
l.push(zip(data._kl[data._vl[i][0]], data._vl[i]));
}
return l;
},
compress: function(doclist) {
var keys = {}; var values = [];
function get_key_list(doctype) {
// valid standard keys
var key_list = ['doctype', 'name', 'docstatus', 'owner', 'parent',
'parentfield', 'parenttype', 'idx', 'creation', 'modified',
'modified_by', '__islocal', '__newname', '__modified',
'_user_tags', '__temp'];

for(key in wn.meta.docfield_map[doctype]) { // all other values
if(!in_list(key_list, key)
&& !in_list(no_value_fields, wn.meta.docfield_map[doctype][key].fieldtype)
&& !wn.meta.docfield_map[doctype][key].no_column) {
key_list[key_list.length] = key
}
}
return key_list;
}
for(var i=0; i<doclist.length;i++) {
var doc = doclist[i];
// make keys
if(!keys[doc.doctype]) {
keys[doc.doctype] = get_key_list(doc.doctype);
// doctype must be first
}
var row = []
var key_list = keys[doc.doctype];
// make data rows
for(var j=0;j<key_list.length;j++) {
row.push(doc[key_list[j]]);
}
values.push(row);
}

return JSON.stringify({'_vl':values, '_kl':keys});
}
});

+ 3
- 2
public/js/wn/provide.js View File

@@ -40,5 +40,6 @@ wn._ = function(txt) {
return txt;
}

wn.provide('wn.settings');
wn.provide('wn.ui');
wn.provide("locals");
wn.provide("wn.settings");
wn.provide("wn.ui");

+ 2
- 2
public/js/wn/request.js View File

@@ -87,7 +87,7 @@ wn.request.cleanup = function(opts, r) {

// sync docs
if(r.docs) {
LocalDB.sync(r.docs);
wn.model.sync(r.docs);
}
wn.last_response = r;
@@ -148,7 +148,7 @@ wn.call = function(opts) {
} else if(opts.doc) {
$.extend(args, {
cmd: "runserverobj",
docs: compress_doclist(wn.model.get_doclist(opts.doc.doctype,
docs: wn.model.compress(wn.model.get_doclist(opts.doc.doctype,
opts.doc.name)),
method: opts.method,
args: opts.args,


+ 1
- 1
public/js/wn/ui/listing.js View File

@@ -65,7 +65,7 @@ wn.ui.Listing = Class.extend({
if(wn.boot.profile.can_create.indexOf(this.opts.new_doctype)==-1) {
this.opts.new_doctype = null;
} else {
this.opts.new_doctype = get_doctype_label(this.opts.new_doctype);
this.opts.new_doctype = wn._(this.opts.new_doctype);
}
}
if(!this.opts.no_result_message) {


+ 1
- 1
public/js/wn/ui/themes.js View File

@@ -10,7 +10,7 @@ wn.ui.set_user_background = function(src) {
wn.ui.themes = {
"Default": {
sidebar: "#f2f2f2",
titlebar: "#dfdfdf",
titlebar: "#d2d2d2",
toolbar: "#e9e9e9"
},
Desert: {


+ 1
- 1
public/js/wn/ui/toolbar/selector_dialog.js View File

@@ -82,7 +82,7 @@ wn.ui.toolbar.SelectorDialog = Class.extend({
set_values: function(lst) {
// convert to labels
for(var i=0;i<lst.length;i++)
lst[i]=get_doctype_label(lst[i]);
lst[i]=wn._(lst[i]);
// set values
var sel = this.dialog.fields_dict.doctype.input;


+ 1
- 1
public/js/wn/views/doclistview.js View File

@@ -45,7 +45,7 @@ wn.views.doclistview.show = function(doctype) {
wn.views.DocListView = wn.ui.Listing.extend({
init: function(doctype) {
this.doctype = doctype;
this.label = get_doctype_label(doctype);
this.label = wn._(doctype);
this.label = (this.label.toLowerCase().substr(-4) == 'list') ?
this.label : (this.label + ' List');
this.make_page();


+ 2
- 2
public/js/wn/views/formview.js View File

@@ -15,7 +15,7 @@ wn.views.formview = {
if(!(locals[dt] && locals[dt][dn])) {
if(dn && dn.substr(0,4)=="New ") {
var new_name = LocalDB.create(dt);
var new_name = wn.model.make_new_doc_and_get_name(dt);
wn.views.formview.show(dt, new_name);
return;
} else {
@@ -33,7 +33,7 @@ wn.views.formview = {
})
},
create: function(dt) {
var new_name = LocalDB.create(dt);
var new_name = wn.model.make_new_doc_and_get_name(dt);
wn.set_route('Form', dt, new_name);
}
}

+ 0
- 1
public/js/wn/views/load_reportview.js View File

@@ -23,7 +23,6 @@
wn.views.reportview = {
show: function(dt, rep_name) {
wn.require('js/report-legacy.js');
dt = get_label_doctype(dt);

if(!_r.rb_con) {
// first load


+ 1
- 1
webnotes/__init__.py View File

@@ -286,7 +286,7 @@ def doclist(lst=None):
from webnotes.model.doclist import DocList
return DocList(lst)

def model_wrapper(doctype, name=None):
def model_wrapper(doctype=None, name=None):
from webnotes.model.wrapper import ModelWrapper
return ModelWrapper(doctype, name)



+ 5
- 1
webnotes/utils/file_manager.py View File

@@ -80,6 +80,10 @@ def save_uploaded():
return None, fname

def save_url(file_url):
if not (file_url.startswith("http://") or file_url.startswith("https://")):
webnotes.msgprint("URL must start with 'http://' or 'https://'")
return None, None
f = webnotes.doc("File Data")
f.file_url = file_url
f.file_name = file_url.split('/')[-1]
@@ -93,7 +97,7 @@ def get_uploaded_content():
webnotes.uploaded_filename, webnotes.uploaded_content = i.filename, i.file.read()
return webnotes.uploaded_filename, webnotes.uploaded_content
else:
webnotes.msgprint('No File');
webnotes.msgprint('No File')
return None, None

def save_file(fname, content, module=None):


+ 1
- 0
webnotes/widgets/form/load.py View File

@@ -23,6 +23,7 @@
from __future__ import unicode_literals
import webnotes
import webnotes.model.doc
import webnotes.utils

@webnotes.whitelist()
def getdoc():


+ 24
- 16
webnotes/widgets/form/save.py View File

@@ -25,32 +25,40 @@ import webnotes

@webnotes.whitelist()
def savedocs():
"""save / submit / cancel / update doclist"""
"""save / submit / update doclist"""
try:
from webnotes.model.wrapper import ModelWrapper
form = webnotes.form_dict

doclist = ModelWrapper()
doclist.from_compressed(form.get('docs'), form.get('docname'))
doclist = webnotes.model_wrapper()
doclist.from_compressed(webnotes.form_dict.docs, webnotes.form_dict.docname)

# action
action = form.get('action')

action = webnotes.form_dict.action
if action=='Update': action='update_after_submit'

getattr(doclist, action.lower())()

# update recent documents
webnotes.user.update_recent(doclist.doc.doctype, doclist.doc.name)
send_updated_docs(doclist)

# send updated docs
webnotes.response['saved'] = '1'
webnotes.response['main_doc_name'] = doclist.doc.name
webnotes.response['doctype'] = doclist.doc.doctype
webnotes.response['docname'] = doclist.doc.name
webnotes.response['docs'] = [doclist.doc] + doclist.children
except Exception, e:
webnotes.msgprint(webnotes._('Did not save'))
webnotes.errprint(webnotes.utils.getTraceback())
raise e

@webnotes.whitelist()
def cancel(doctype=None, name=None):
"""cancel a doclist"""
try:
doclist = webnotes.model_wrapper(doctype, name)
doclist.cancel()
send_updated_docs(doclist)
except Exception, e:
webnotes.msgprint('Did not save')
webnotes.errprint(webnotes.utils.getTraceback())
webnotes.msgprint(webnotes._("Did not cancel"))
raise e
def send_updated_docs(doclist):
webnotes.response['main_doc_name'] = doclist.doc.name
webnotes.response['doctype'] = doclist.doc.doctype
webnotes.response['docname'] = doclist.doc.name
webnotes.response['docs'] = [doclist.doc] + doclist.children

Loading…
Cancel
Save