From 467c36ef08e0688a1b7cac8ca15098e8c9d5ad92 Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Thu, 12 Sep 2013 17:01:51 +0530 Subject: [PATCH 1/4] [minor] install fixes --- core/doctype/doctype/doctype.py | 7 +- core/doctype/profile/profile.py | 19 ++-- public/build.json | 18 ++-- public/js/wn/form/attachments.js | 2 +- public/js/wn/form/control.js | 2 +- public/js/wn/misc/utils.js | 9 +- webnotes/auth.py | 5 +- webnotes/install_lib/install.py | 6 ++ webnotes/model/bean.py | 5 +- webnotes/model/doc.py | 10 +- webnotes/utils/datautils.py | 41 +++----- webnotes/utils/email_lib/smtp.py | 7 +- webnotes/utils/file_manager.py | 47 +++++---- website/css/website.css | 57 +++------- website/js/website.js | 157 +++++++++++++++++----------- website/templates/includes/login.js | 19 ++-- website/templates/pages/login.html | 2 +- 17 files changed, 221 insertions(+), 192 deletions(-) diff --git a/core/doctype/doctype/doctype.py b/core/doctype/doctype/doctype.py index d07ab9c0d3..ae1d1271b4 100644 --- a/core/doctype/doctype/doctype.py +++ b/core/doctype/doctype/doctype.py @@ -103,13 +103,10 @@ class DocType: # update index if not self.doc.custom: - from webnotes.modules import scrub - doctype = scrub(self.doc.name) - module = __import__(scrub(self.doc.module) + ".doctype." + doctype + "." + doctype, - fromlist=[""]) + from webnotes.model.code import load_doctype_module + module = load_doctype_module( self.doc.name, self.doc.module) if hasattr(module, "on_doctype_update"): module.on_doctype_update() - webnotes.clear_cache(doctype=self.doc.name) def check_link_replacement_error(self): diff --git a/core/doctype/profile/profile.py b/core/doctype/profile/profile.py index 393c9dfa50..35961c1b80 100644 --- a/core/doctype/profile/profile.py +++ b/core/doctype/profile/profile.py @@ -91,8 +91,8 @@ class DocType: if self.in_insert: webnotes.msgprint("New user created. - %s" % self.doc.name) if cint(self.doc.send_invite_email): - webnotes.msgprint("Sent welcome mail.") self.send_welcome_mail(self.doc.new_password) + webnotes.msgprint("Sent welcome mail.") else: self.password_reset_mail(self.doc.new_password) webnotes.msgprint("Password updated.") @@ -129,12 +129,10 @@ To login to %(product)s, please go to: Thank you,
%(user_fullname)s """ - import startup - self.send_login_mail("Your " +startup.product_name + " password has been reset", txt, password) + self.send_login_mail("Your " + webnotes.get_config().get("app_name") + " password has been reset", txt, password) def send_welcome_mail(self, password): """send welcome mail to user with password and login url""" - import startup txt = """ ## %(company)s @@ -153,25 +151,28 @@ To login to your new %(product)s account, please go to: Thank you,
%(user_fullname)s """ - self.send_login_mail("Welcome to " + startup.product_name, txt, password) + self.send_login_mail("Welcome to " + webnotes.get_config().get("app_name"), txt, password) def send_login_mail(self, subject, txt, password): """send mail with login details""" import os - import startup from webnotes.utils.email_lib import sendmail_md from webnotes.profile import get_user_fullname from webnotes.utils import get_request_site_address + + full_name = get_user_fullname(webnotes.session['user']) + if full_name == "Guest": + full_name = "Administrator" args = { 'first_name': self.doc.first_name or self.doc.last_name or "user", 'user': self.doc.name, 'password': password, - 'company': webnotes.conn.get_default('company') or startup.product_name, + 'company': webnotes.conn.get_default('company') or webnotes.get_config().get("app_name"), 'login_url': get_request_site_address(), - 'product': startup.product_name, - 'user_fullname': get_user_fullname(webnotes.session['user']) + 'product': webnotes.get_config().get("app_name"), + 'user_fullname': full_name } sender = webnotes.session.user not in ("Administrator", "Guest") and webnotes.session.user or None diff --git a/public/build.json b/public/build.json index 1c8985f907..f25bd3d674 100644 --- a/public/build.json +++ b/public/build.json @@ -3,9 +3,19 @@ "public/css/all-web.css": [ "lib/public/css/bootstrap.css", "lib/public/css/font-awesome.css", + "lib/public/css/nprogress.css", "lib/website/css/website.css" ] }, + + { + "public/js/all-web.min.js": [ + "lib/public/js/lib/bootstrap.min.js", + "lib/public/js/wn/misc/number_format.js", + "lib/public/js/lib/nprogress.js", + "lib/website/js/website.js" + ] + }, { "public/css/all-app.css": [ @@ -23,14 +33,6 @@ "lib/public/css/nprogress.css", ] }, - - { - "public/js/all-web.min.js": [ - "lib/public/js/lib/bootstrap.min.js", - "lib/public/js/wn/misc/number_format.js", - "lib/website/js/website.js" - ] - }, { "public/js/all-app.min.js": [ diff --git a/public/js/wn/form/attachments.js b/public/js/wn/form/attachments.js index 9a2a976004..36018a2652 100644 --- a/public/js/wn/form/attachments.js +++ b/public/js/wn/form/attachments.js @@ -141,7 +141,7 @@ wn.ui.form.Attachments = Class.extend({ this.add_to_attachments(fileid, filename); this.refresh(); if(fieldname) { - this.frm.set_value(fieldname, "files/"+filename); + this.frm.set_value(fieldname, wn.utils.get_file_link(filename)); this.frm.cscript[fieldname] && this.frm.cscript[fieldname](this.frm.doc); } } diff --git a/public/js/wn/form/control.js b/public/js/wn/form/control.js index 9b96190da0..71a95b55a7 100644 --- a/public/js/wn/form/control.js +++ b/public/js/wn/form/control.js @@ -568,7 +568,7 @@ wn.ui.form.ControlSelect = wn.ui.form.ControlData.extend({ this.set_description(""); var options = [""]; for(var fname in fl) { - if(fname.substr(0,4)!="http") + if(fname.indexOf("/")===-1) fname = "files/" + fname; options.push(fname); } diff --git a/public/js/wn/misc/utils.js b/public/js/wn/misc/utils.js index de5d58080e..1497e6902b 100644 --- a/public/js/wn/misc/utils.js +++ b/public/js/wn/misc/utils.js @@ -5,8 +5,13 @@ wn.provide('wn.utils'); wn.utils = { get_file_link: function(filename) { - return wn.utils.is_url(filename) || (filename.indexOf("images/")!=-1) || (filename.indexOf("files/")!=-1) - ? filename : 'files/' + filename; + if(wn.utils.is_url(filename)) { + return filename; + } else if(filename.indexOf("/")===-1) { + return "files/" + filename; + } else { + return filename; + } }, is_html: function(txt) { if(txt.indexOf("
")==-1 && txt.indexOf("') + .html('

' + +text+'
').appendTo(document.body); + }, + hide_message: function(text) { + $('.message-overlay').remove(); + }, + call: function(opts) { + wn.prepare_call(opts); + $.ajax({ + type: "POST", + url: "server.py", + data: opts.args, + dataType: "json", + success: function(data) { + wn.process_response(opts, data); + }, + error: function(response) { + NProgress.done(); + console.error ? console.error(response) : console.log(response); + } + }); + + return false; + }, + prepare_call: function(opts) { + if(opts.btn) { + $(opts.btn).prop("disabled", true); } - }); - $.ajax({ - type: "POST", - url: "server.py", - data: opts.args, - dataType: "json", - success: function(data) { + if(opts.msg) { + $(opts.msg).toggle(false); + } + + if(!opts.args) opts.args = {}; + + // get or post? + if(!opts.args._type) { + opts.args._type = opts.type || "GET"; + } + + // method + if(opts.method) { + opts.args.cmd = opts.method; + } + + // stringify + $.each(opts.args, function(key, val) { + if(typeof val != "string") { + opts.args[key] = JSON.stringify(val); + } + }); + + NProgress.start(); + }, + process_response: function(opts, data) { + NProgress.done(); + if(opts.btn) { + $(opts.btn).prop("disabled", false); + } + if(data.exc) { if(opts.btn) { - $(opts.btn).prop("disabled", false); + $(opts.btn).addClass("btn-danger"); + setTimeout(function() { $(opts.btn).removeClass("btn-danger"); }, 1000); } - if(data.exc) { - if(opts.btn) { - $(opts.btn).addClass("btn-danger"); - setTimeout(function() { $(opts.btn).removeClass("btn-danger"); }, 1000); - } - try { - var err = JSON.parse(data.exc); - if($.isArray(err)) { - err = err.join("\n"); - } - console.error ? console.error(err) : console.log(err); - } catch(e) { - console.log(data.exc); - } - } else{ - if(opts.btn) { - $(opts.btn).addClass("btn-success"); - setTimeout(function() { $(opts.btn).removeClass("btn-success"); }, 1000); + try { + var err = JSON.parse(data.exc); + if($.isArray(err)) { + err = err.join("\n"); } + console.error ? console.error(err) : console.log(err); + } catch(e) { + console.log(data.exc); } - if(opts.msg && data.message) { - $(opts.msg).html(data.message).toggle(true); + } else{ + if(opts.btn) { + $(opts.btn).addClass("btn-success"); + setTimeout(function() { $(opts.btn).removeClass("btn-success"); }, 1000); } - if(opts.callback) - opts.callback(data); - }, - error: function(response) { - console.error ? console.error(response) : console.log(response); } - }); - - return false; + if(opts.msg && data.message) { + $(opts.msg).html(data.message).toggle(true); + } + if(opts.callback) + opts.callback(data); + }, + show_message: function(text, icon) { + if(!icon) icon="icon-refresh icon-spin"; + wn.hide_message(); + $('
') + .html('

' + +text+'
').appendTo(document.body); + }, + hide_message: function(text) { + $('.message-overlay').remove(); + }, + get_sid: function() { + var sid = getCookie("sid"); + return sid && sid!=="Guest"; + } } + // Utility functions function valid_email(id) { diff --git a/website/templates/includes/login.js b/website/templates/includes/login.js index 1ef976a7b8..1d0e3339fb 100644 --- a/website/templates/includes/login.js +++ b/website/templates/includes/login.js @@ -49,7 +49,7 @@ login.do_login = function(){ $('#login_btn').prop("disabled", true); $("#login-spinner").toggle(true); $('#login_message').toggle(false); - + $.ajax({ type: "POST", url: "server.py", @@ -69,7 +69,7 @@ login.do_login = function(){ window.location.href = "index"; } } else { - login.set_message(data.message); + login.set_message(data.message || data._server_messages); } } }) @@ -77,9 +77,14 @@ login.do_login = function(){ return false; } +login.set_heading = function(html) { + $(".panel-heading").html("

" + html + "

"); +} + login.show_login = function() { + login.set_heading(' Login'); $("#login_wrapper h3").html("Login"); - $("#login-label").html("Email Id"); + $("#login_id").attr("placeholder", "Login Email Id"); $("#password-row").toggle(true); $("#full-name-row, #login_message").toggle(false); $("#login_btn").html("Login").removeClass("btn-success"); @@ -98,8 +103,8 @@ login.show_login = function() { } login.show_sign_up = function() { - $("#login_wrapper h3").html("Sign Up"); - $("#login-label").html("Email Id"); + login.set_heading(' Sign Up'); + $("#login_id").attr("placeholder", "Your Email Id"); $("#password-row, #login_message").toggle(false); $("#full-name-row").toggle(true); $("#login_btn").html("Sign Up").addClass("btn-success"); @@ -108,8 +113,8 @@ login.show_sign_up = function() { } login.show_forgot_password = function() { - $("#login_wrapper h3").html("Forgot"); - $("#login-label").html("Email Id"); + login.set_heading(' Forgot'); + $("#login_id").attr("placeholder", "Your Email Id"); $("#password-row, #login_message, #full-name-row").toggle(false); $("#login_btn").html("Send Password").removeClass("btn-success"); $("#switch-view").html("Login"); diff --git a/website/templates/pages/login.html b/website/templates/pages/login.html index 70bcdbbbd4..0c35d49ab7 100644 --- a/website/templates/pages/login.html +++ b/website/templates/pages/login.html @@ -25,7 +25,7 @@
Date: Thu, 12 Sep 2013 17:09:17 +0530 Subject: [PATCH 2/4] [minor] check create permission separately --- webnotes/__init__.py | 2 +- webnotes/model/bean.py | 11 ++++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/webnotes/__init__.py b/webnotes/__init__.py index a6aa1ad2a5..5ac03096ff 100644 --- a/webnotes/__init__.py +++ b/webnotes/__init__.py @@ -278,7 +278,7 @@ def has_permission(doctype, ptype="read", refdoc=None): and ifnull(p.permlevel,0) = 0 and (p.role="All" or p.role in (select `role` from tabUserRole where `parent`=%s)) """ % ("%s", ptype, "%s"), (doctype, session.user), as_dict=1) - + if refdoc: match_failed = {} for p in perms: diff --git a/webnotes/model/bean.py b/webnotes/model/bean.py index e2ac0e9371..f422daac68 100644 --- a/webnotes/model/bean.py +++ b/webnotes/model/bean.py @@ -313,8 +313,13 @@ class Bean: return webnotes.has_permission(self.doc.doctype, "read", self.doc) def save(self, check_links=1): - perm = "create" if self.doc.fields.get("__islocal") else "write" - if self.ignore_permissions or webnotes.has_permission(self.doc.doctype, perm, self.doc): + perm_to_check = "write" + if self.doc.fields.get("__islocal"): + perm_to_check = "create" + if not self.doc.owner: + self.doc.owner = webnotes.session.user + + if self.ignore_permissions or webnotes.has_permission(self.doc.doctype, perm_to_check, self.doc): self.to_docstatus = 0 self.prepare_for_save("save") if not self.ignore_validate: @@ -325,7 +330,7 @@ class Bean: self.save_children() self.run_method('on_update') else: - self.no_permission_to(_(perm.title())) + self.no_permission_to(_(perm_to_check.title())) return self From 4d55677114542135793da6e26baa27df011c346d Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Thu, 12 Sep 2013 18:36:26 +0530 Subject: [PATCH 3/4] [minor] [fix] [import] --- core/page/data_import_tool/data_import_tool.py | 6 ++++++ webnotes/install_lib/install.py | 15 ++++++--------- webnotes/utils/datautils.py | 2 +- wnf.py | 14 ++++++++++---- 4 files changed, 23 insertions(+), 14 deletions(-) diff --git a/core/page/data_import_tool/data_import_tool.py b/core/page/data_import_tool/data_import_tool.py index e151ddee03..0f2dbf514a 100644 --- a/core/page/data_import_tool/data_import_tool.py +++ b/core/page/data_import_tool/data_import_tool.py @@ -479,3 +479,9 @@ def delete_child_rows(rows, doctype): """delete child rows for all parents""" for p in list(set([r[1] for r in rows])): webnotes.conn.sql("""delete from `tab%s` where parent=%s""" % (doctype, '%s'), p) + +def import_file_by_path(path): + from webnotes.utils.datautils import read_csv_content + print "Importing " + path + with open(path, "r") as infile: + upload(rows = read_csv_content(infile.read())) diff --git a/webnotes/install_lib/install.py b/webnotes/install_lib/install.py index 5acccadded..751d25d540 100755 --- a/webnotes/install_lib/install.py +++ b/webnotes/install_lib/install.py @@ -87,7 +87,7 @@ class Installer: if os.path.exists("app"): sync_for("app", force=True, sync_everything=True) - + if os.path.exists(os.path.join("app", "startup", "install_fixtures")): self.import_fixtures() @@ -114,15 +114,12 @@ class Installer: webnotes.conn.commit() if f.endswith(".csv"): - from core.page.data_import_tool import data_import_tool - from webnotes.utils.datautils import read_csv_content - print "Importing " + f - with open(os.path.join(basepath, f), "r") as infile: - data_import_tool.upload(rows = read_csv_content(infile.read())) - webnotes.conn.commit() + from core.page.data_import_tool.data_import_tool import import_file_by_path + import_file_by_path(os.path.join(basepath, f)) + webnotes.conn.commit() - if os.path.exists("app", "startup", "install_fixtures", "files"): - if not os.path.exists("public", "files"): + if os.path.exists(os.path.join("app", "startup", "install_fixtures", "files")): + if not os.path.exists(os.path.join("public", "files")): os.makedirs(os.path.join("public", "files")) os.system("cp -r %s %s/" % (os.path.join("app", "startup", "install_fixtures", "files"), os.path.join("public", "files"))) diff --git a/webnotes/utils/datautils.py b/webnotes/utils/datautils.py index f81ad9ea5c..231a0ccc34 100644 --- a/webnotes/utils/datautils.py +++ b/webnotes/utils/datautils.py @@ -38,7 +38,7 @@ def read_csv_content(fcontent, ignore_encoding=False): decoded = False for encoding in ["utf-8", "windows-1250", "windows-1252"]: try: - fcontent = unicode(encoding) + fcontent = unicode(fcontent, encoding) decoded = True break except UnicodeDecodeError, e: diff --git a/wnf.py b/wnf.py index 9d7c96d1bb..cc0b302f38 100755 --- a/wnf.py +++ b/wnf.py @@ -537,14 +537,20 @@ def run(): import json if os.path.isdir(options.import_doclist): docs = [os.path.join(options.import_doclist, f) \ - for f in os.listdir(options.import_doclist) if f.endswith(".json")] + for f in os.listdir(options.import_doclist)] else: docs = [options.import_doclist] for f in docs: - with open(f, "r") as infile: - b = webnotes.bean(json.loads(infile.read())).insert_or_update() - print "Imported: " + b.doc.doctype + " / " + b.doc.name + if f.endswith(".json"): + with open(f, "r") as infile: + b = webnotes.bean(json.loads(infile.read())).insert_or_update() + print "Imported: " + b.doc.doctype + " / " + b.doc.name + webnotes.conn.commit() + if f.endswith(".csv"): + from core.page.data_import_tool.data_import_tool import import_file_by_path + import_file_by_path(f) + webnotes.conn.commit() elif options.reset_perms: for d in webnotes.conn.sql_list("""select name from `tabDocType` From 49d833e72b037cc5229fbd652790089bd8ab528f Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Fri, 13 Sep 2013 10:21:19 +0530 Subject: [PATCH 4/4] [editor] [fix] [minor] --- public/js/wn/form/editors.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/public/js/wn/form/editors.js b/public/js/wn/form/editors.js index 303639684f..e5cb266d8d 100644 --- a/public/js/wn/form/editors.js +++ b/public/js/wn/form/editors.js @@ -157,8 +157,9 @@ wn.editors.BootstrapWYSIWYG = Class.extend({ me.$textarea.val(html_beautify(me.$editor.cleanHtml())); me.$parent.find(".for-rich-text").toggle(false); me.$parent.find(".for-html").toggle(true); - me.$parent.find(".btn-html").addClass("btn-info").prop("disabled", true); - me.$parent.find(".btn-rich-text").removeClass("btn-info").prop("disabled", false); + console.log(me.$parent.find(".btn-html")); + me.$parent.find(".btn-html").attr("disabled", "disabled"); + me.$parent.find(".btn-rich-text").attr("disabled", false); me.current_editor = me.$textarea; }); @@ -167,8 +168,9 @@ wn.editors.BootstrapWYSIWYG = Class.extend({ me.$editor.html(me.$textarea.val()); me.$parent.find(".for-rich-text").toggle(true); me.$parent.find(".for-html").toggle(false); - me.$parent.find(".btn-html").removeClass("btn-info").prop("disabled", false); - me.$parent.find(".btn-rich-text").addClass("btn-info").prop("disabled", true); + + me.$parent.find(".btn-rich-text").attr("disabled", "disabled"); + me.$parent.find(".btn-html").attr("disabled", false); me.current_editor = me.$editor; });