@@ -167,7 +167,12 @@ def get_template(): | |||
w.writerow([data_keys.data_separator]) | |||
def add_data(): | |||
def add_data_row(row_group, dt, d, rowidx): | |||
def add_data_row(row_group, dt, doc, rowidx): | |||
d = doc.copy() | |||
if all_doctypes: | |||
d.name = '"'+ d.name+'"' | |||
d.modified = '"'+ d.modified+'"' | |||
if len(row_group) < rowidx + 1: | |||
row_group.append([""] * (len(columns) + 1)) | |||
row = row_group[rowidx] | |||
@@ -180,8 +185,6 @@ def get_template(): | |||
for doc in data: | |||
# add main table | |||
row_group = [] | |||
if all_doctypes: | |||
doc.modified = '"'+ doc.modified+'"' | |||
add_data_row(row_group, doctype, doc, 0) | |||
@@ -311,6 +314,11 @@ def upload(): | |||
d[fieldname] = flt(d[fieldname]) | |||
except IndexError, e: | |||
pass | |||
# scrub quotes from name and modified | |||
for fieldname in ("name", "modified"): | |||
if d.get(fieldname) and d[fieldname].startswith('"'): | |||
d[fieldname] = d[fieldname][1:-1] | |||
if sum([0 if not val else 1 for val in d.values()]): | |||
d['doctype'] = dt | |||
@@ -385,7 +393,6 @@ def upload(): | |||
bean = webnotes.bean(doclist) | |||
if overwrite and bean.doc.modified: | |||
# remove the extra quotes added to preserve date formatting | |||
bean.doc.modified = bean.doc.modified[1:-1] | |||
bean.save() | |||
ret.append('Updated row (#%d) %s' % (row_idx + 1, getlink(bean.doc.doctype, bean.doc.name))) | |||
else: | |||
@@ -135,14 +135,14 @@ | |||
}, | |||
{ | |||
"public/js/slickgrid.min.js": [ | |||
'lib/public/js/lib/slickgrid/jquery.event.drag.min.js', | |||
'lib/public/js/lib/slickgrid/plugins/slick.cellrangedecorator.js', | |||
'lib/public/js/lib/slickgrid/plugins/slick.cellrangeselector.js', | |||
'lib/public/js/lib/slickgrid/plugins/slick.cellselectionmodel.js', | |||
'lib/public/js/lib/slickgrid/plugins/slick.cellexternalcopymanager.js', | |||
'lib/public/js/lib/slickgrid/slick.core.js', | |||
'lib/public/js/lib/slickgrid/slick.grid.js', | |||
'lib/public/js/lib/slickgrid/slick.dataview.js', | |||
"lib/public/js/lib/slickgrid/jquery.event.drag.min.js", | |||
"lib/public/js/lib/slickgrid/plugins/slick.cellrangedecorator.js", | |||
"lib/public/js/lib/slickgrid/plugins/slick.cellrangeselector.js", | |||
"lib/public/js/lib/slickgrid/plugins/slick.cellselectionmodel.js", | |||
"lib/public/js/lib/slickgrid/plugins/slick.cellexternalcopymanager.js", | |||
"lib/public/js/lib/slickgrid/slick.core.js", | |||
"lib/public/js/lib/slickgrid/slick.grid.js", | |||
"lib/public/js/lib/slickgrid/slick.dataview.js", | |||
] | |||
} | |||
] | |||
@@ -238,7 +238,7 @@ function prettyDate(time){ | |||
if ( isNaN(day_diff) || day_diff < 0 ) | |||
return ''; | |||
return day_diff == 0 && ( | |||
return when = day_diff == 0 && ( | |||
diff < 60 && "just now" || | |||
diff < 120 && "1 minute ago" || | |||
diff < 3600 && Math.floor( diff / 60 ) + " minutes ago" || | |||
@@ -249,20 +249,23 @@ function prettyDate(time){ | |||
day_diff < 31 && Math.ceil( day_diff / 7 ) + " weeks ago" || | |||
day_diff < 365 && Math.ceil( day_diff / 30) + " months ago" || | |||
"> " + Math.floor( day_diff / 365 ) + " year(s) ago"; | |||
} | |||
// If jQuery is included in the page, adds a jQuery plugin to handle it as well | |||
if ( typeof jQuery != "undefined" ) | |||
jQuery.fn.prettyDate = function(){ | |||
return this.each(function(){ | |||
var date = prettyDate(this.title); | |||
if ( date ) | |||
jQuery(this).text( date ); | |||
}); | |||
}; | |||
var comment_when = prettyDate; | |||
var comment_when = function(datetime) { | |||
return '<span class="wn-timestamp" data-timestamp="'+datetime+'">' + prettyDate(datetime) + '</span>'; | |||
}; | |||
wn.datetime.comment_when = prettyDate; | |||
wn.datetime.refresh_when = function() { | |||
if(jQuery) { | |||
$(".wn-timestamp").each(function() { | |||
$(this).html(prettyDate($(this).attr("data-timestamp"))); | |||
}) | |||
} | |||
} | |||
setInterval(function() { wn.datetime.refresh_when() }, 60000); // refresh every minute | |||
// globals (deprecate) | |||
var date = dateutil = wn.datetime; | |||
@@ -46,12 +46,10 @@ wn.upload = { | |||
}, | |||
upload_file: function(fileobj, args, callback, onerror) { | |||
if(!fileobj && !args.file_url) { | |||
msgprint(_("Please attach a file or set a URL")); | |||
msgprint(wn._("Please attach a file or set a URL")); | |||
return; | |||
} | |||
var _upload_file = function() { | |||
var msgbox = msgprint(wn._("Uploading...")); | |||
return wn.call({ | |||
@@ -67,7 +67,7 @@ def submit(doclist): | |||
doclistobj = webnotes.bean(doclist) | |||
doclistobj.submit() | |||
return [d.fields for d in doclist] | |||
@webnotes.whitelist() | |||
@@ -388,6 +388,9 @@ class Database: | |||
if field!="modified": | |||
self.set_value(dt, dn, "modified", modified or now()) | |||
def set_in_doc(self, doc, field, val): | |||
self.set(doc, field, val) | |||
def set(self, doc, field, val): | |||
from webnotes.utils import now | |||
doc.modified = now() | |||
@@ -386,15 +386,16 @@ class Document: | |||
self.set_idx() | |||
# if required, make new | |||
if self.fields.get('__islocal') and (not res.get('issingle')): | |||
r = self._insert(res.get('autoname'), res.get('istable'), res.get('name_case'), | |||
make_autoname, keep_timestamps = keep_timestamps) | |||
if r: | |||
return r | |||
else: | |||
if not res.get('issingle') and not webnotes.conn.exists(self.doctype, self.name): | |||
webnotes.msgprint("""This document was updated before your change. Please refresh before saving.""", raise_exception=1) | |||
if not res.get('issingle'): | |||
if self.fields.get('__islocal'): | |||
r = self._insert(res.get('autoname'), res.get('istable'), res.get('name_case'), | |||
make_autoname, keep_timestamps = keep_timestamps) | |||
if r: | |||
return r | |||
else: | |||
if not webnotes.conn.exists(self.doctype, self.name): | |||
webnotes.msgprint(webnotes._("Cannot update a non-exiting record, try inserting.") + ": " + self.doctype + " / " + self.name, | |||
raise_exception=1) | |||
# save the values | |||
self._update_values(res.get('issingle'), | |||
@@ -62,7 +62,7 @@ def get_uploaded_content(): | |||
return None, None | |||
def save_file(fname, content, dt, dn): | |||
from filecmp import cmp | |||
import filecmp | |||
files_path = get_files_path() | |||
file_size = check_max_file_size(content) | |||
@@ -78,7 +78,7 @@ def save_file(fname, content, dt, dn): | |||
if versions: | |||
found_match = False | |||
for version in versions: | |||
if cmp(os.path.join(files_path, version), temp_fname): | |||
if filecmp.cmp(os.path.join(files_path, version), temp_fname): | |||
# remove new file, already exists! | |||
os.remove(temp_fname) | |||
fname = version | |||
@@ -126,7 +126,7 @@ def get_new_fname_based_on_version(files_path, main, extn, versions): | |||
return new_fname | |||
def scrub_file_name(fname): | |||
def scrub_file_name(fname): | |||
if '\\' in fname: | |||
fname = fname.split('\\')[-1] | |||
if '/' in fname: | |||
@@ -27,10 +27,7 @@ def render_page(page_name): | |||
"""get page html""" | |||
page_name = scrub_page_name(page_name) | |||
html = '' | |||
if page_name=="index": | |||
page_name = get_home_page() | |||
if not (hasattr(conf, 'auto_cache_clear') and conf.auto_cache_clear or 0): | |||
html = webnotes.cache().get_value("page:" + page_name) | |||
from_cache = True | |||
@@ -65,7 +62,13 @@ def build_page(page_name): | |||
page_options = sitemap.get(page_name) | |||
if not page_options: | |||
raise PageNotFoundError | |||
if page_name=="index": | |||
# page not found, try home page | |||
page_options = sitemap.get(get_home_page()) | |||
if not page_options: | |||
raise PageNotFoundError | |||
else: | |||
raise PageNotFoundError | |||
basepath = webnotes.utils.get_base_path() | |||
module = None | |||
@@ -141,6 +141,11 @@ div.web-footer { | |||
} | |||
} | |||
.navbar { | |||
box-shadow: none; | |||
border-radius: 0px; | |||
} | |||
.panel-heading, | |||
.panel-body { | |||
padding-left: 15px; | |||
@@ -71,8 +71,6 @@ div.web-footer, div.web-footer a { | |||
} | |||
.navbar { | |||
box-shadow: none; | |||
border-radius: 0px; | |||
background-color: #{{ doc.top_bar_background}}; | |||
background-repeat: repeat-x; | |||
background-image: none; | |||
@@ -12,8 +12,9 @@ | |||
<link type="text/css" rel="stylesheet" href="css/wn-web.css"> | |||
<link rel="shortcut icon" href="{{ favicon }}" type="image/x-icon"> | |||
<link rel="icon" href="{{ favicon }}" type="image/x-icon"> | |||
{% if meta_description -%}<meta name="description" content="{{ meta_description }}"> | |||
{%- endif %} | |||
{% block head %}{% endblock %} | |||
{% if meta_description -%} | |||
<meta name="description" content="{{ meta_description }}">{%- endif %} | |||
{% block javascript -%} | |||
{% if javascript %}<script>{{ javascript }}</script>{% endif %} | |||
{%- endblock %} | |||
@@ -282,6 +282,14 @@ def setup_options(): | |||
parser.add_option("--make_conf", default=False, action="store_true", | |||
help="Create new conf.py file") | |||
# bean helpers | |||
parser.add_option('--export_doclist', nargs=3, metavar="DOCTYPE NAME PATH", | |||
help="""Export doclist as json to the given path, use '-' as name for Singles.""") | |||
parser.add_option('--import_doclist', nargs=1, metavar="PATH", | |||
help="""Import (insert/update) doclist. If the argument is a directory, all files ending with .json are imported""") | |||
return parser.parse_args() | |||
def run(): | |||
@@ -511,6 +519,33 @@ def run(): | |||
from core.doctype.documentation_tool.documentation_tool import write_static | |||
write_static() | |||
elif options.export_doclist: | |||
import json | |||
from webnotes.handler import json_handler | |||
args = list(options.export_doclist) | |||
if args[1]=="-": args[1] = args[0] | |||
with open(args[2], "w") as outfile: | |||
outfile.write(json.dumps([d.fields for d in \ | |||
webnotes.bean(args[0], args[1]).doclist], default=json_handler, indent=1, sort_keys=True)) | |||
elif options.import_doclist: | |||
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")] | |||
else: | |||
docs = [options.import_doclist] | |||
for f in docs: | |||
with open(f, "r") as infile: | |||
doclist = json.loads(infile.read()) | |||
if webnotes.conn.exists(doclist[0]["doctype"], doclist[0]["name"]): | |||
b = webnotes.bean(doclist).save() | |||
print "Updated: %s, %s" % (b.doc.doctype, b.doc.name) | |||
else: | |||
b = webnotes.bean(doclist).insert() | |||
print "Inserted: %s, %s" % (b.doc.doctype, b.doc.name) | |||
elif options.reset_perms: | |||
for d in webnotes.conn.sql_list("""select name from `tabDocType` | |||
where ifnull(istable, 0)=0 and ifnull(custom, 0)=0"""): | |||