diff --git a/core/doctype/file_data/file_data.txt b/core/doctype/file_data/file_data.txt
index 728cdf1c92..37ea5f6e9d 100644
--- a/core/doctype/file_data/file_data.txt
+++ b/core/doctype/file_data/file_data.txt
@@ -2,19 +2,16 @@
{
"owner": "Administrator",
"docstatus": 0,
- "creation": "2012-03-27 14:35:37",
+ "creation": "2012-11-30 18:13:34",
"modified_by": "Administrator",
- "modified": "2012-03-27 14:35:37"
+ "modified": "2012-12-11 14:56:34"
},
{
"read_only": 0,
- "section_style": "Simple",
+ "autoname": "FileData/.#####",
"name": "__common__",
- "colour": "White:FFF",
- "module": "Core",
- "server_code_error": " ",
"doctype": "DocType",
- "autoname": "FileData/.#####"
+ "module": "Core"
},
{
"name": "__common__",
@@ -36,6 +33,12 @@
"fieldname": "file_name",
"fieldtype": "Data"
},
+ {
+ "doctype": "DocField",
+ "label": "File URL",
+ "fieldname": "file_url",
+ "fieldtype": "Data"
+ },
{
"oldfieldtype": "Link",
"doctype": "DocField",
@@ -44,13 +47,5 @@
"fieldname": "module",
"fieldtype": "Link",
"options": "Module Def"
- },
- {
- "oldfieldtype": "Blob",
- "doctype": "DocField",
- "label": "Blob Content",
- "oldfieldname": "blob_content",
- "fieldname": "blob_content",
- "fieldtype": "Blob"
}
]
\ No newline at end of file
diff --git a/core/doctype/profile/profile.js b/core/doctype/profile/profile.js
index 163bc2f064..59bacdb85f 100644
--- a/core/doctype/profile/profile.js
+++ b/core/doctype/profile/profile.js
@@ -26,7 +26,7 @@ cur_frm.cscript.refresh = function(doc) {
wn.ui.set_user_background(doc.background_image);
}
if(doc.user_image) {
- wn.boot.user_info[user].image = 'files/' + doc.user_image;
+ wn.boot.user_info[user].image = wn.utils.get_file_link(doc.user_image);
}
}
}
diff --git a/public/build.json b/public/build.json
index bd343f984d..2678025f3c 100644
--- a/public/build.json
+++ b/public/build.json
@@ -143,8 +143,8 @@
"lib/public/js/legacy/widgets/form/form_comments.js",
"lib/public/js/legacy/wn/widgets/form/sidebar.js",
"lib/public/js/legacy/wn/widgets/form/comments.js",
- "lib/public/js/legacy/wn/widgets/form/attachments.js",
"lib/public/js/legacy/wn/widgets/form/assign_to.js",
+ "lib/public/js/wn/form/attachments.js",
"lib/public/js/wn/form/linked_with.js",
"lib/public/js/wn/print/print_table.js",
diff --git a/public/css/ui/views.css b/public/css/ui/views.css
index e6d4d84592..50153ee53f 100644
--- a/public/css/ui/views.css
+++ b/public/css/ui/views.css
@@ -1,3 +1,7 @@
+h5 {
+ margin-bottom: 0px;
+}
+
.layout_wrapper, .layout-wrapper {
-moz-box-shadow: 0px 0px 3px rgba(0,0,0,0.9);
-webkit-box-shadow: 0px 0px 3px rgba(0,0,0,0.9);
diff --git a/public/js/legacy/widgets/form/fields.js b/public/js/legacy/widgets/form/fields.js
index c9e43efa48..74fa654c0b 100644
--- a/public/js/legacy/widgets/form/fields.js
+++ b/public/js/legacy/widgets/form/fields.js
@@ -533,10 +533,11 @@ DateField.prototype.validate = function(v) {
me.input.set_input('');
return '';
}
- var t = v.split('-');
+ var t = $.map(v.split('-'), function(part) { return cint(part) ? part : null; });
if(t.length!=3) { return this.clear(); }
else if(cint(t[1])>12 || cint(t[1])<1) { return this.clear(); }
else if(cint(t[2])>31 || cint(t[2])<1) { return this.clear(); }
+ else if(String(cint(t[0])).length!=4) { return this.clear(); } // 4 char for year
return v;
};
@@ -1101,7 +1102,7 @@ SelectField.prototype.make_input = function() {
this.df.options = '';
var fl = fl.split('\n');
for(var i in fl) {
- this.df.options += '\n' + fl[i].split(',')[1];
+ this.df.options += '\n' + fl[i].split(',')[0];
this.set_description("");
}
} else {
diff --git a/public/js/legacy/widgets/form/form_fields.js b/public/js/legacy/widgets/form/form_fields.js
index fe336e3cc9..85e7868819 100644
--- a/public/js/legacy/widgets/form/form_fields.js
+++ b/public/js/legacy/widgets/form/form_fields.js
@@ -165,7 +165,7 @@ _f.ImageField.prototype.onrefresh = function() {
$(this.label_span).toggle(false);
$(this.wrapper).find("img").remove();
if(this.df.options && this.frm.doc[this.df.options]) {
- $("
")
+ $("
")
.appendTo(this.wrapper);
}
}
diff --git a/public/js/legacy/wn/widgets/form/attachments.js b/public/js/legacy/wn/widgets/form/attachments.js
deleted file mode 100644
index dc6a948116..0000000000
--- a/public/js/legacy/wn/widgets/form/attachments.js
+++ /dev/null
@@ -1,166 +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.
-//
-
-wn.widgets.form.sidebar.Attachments = function(parent, sidebar, doctype, docname) {
- var me = this;
- this.frm = sidebar.form;
-
- this.make = function() {
- if(this.wrapper) this.wrapper.innerHTML = '';
- else this.wrapper = $a(parent, 'div', 'sidebar-comment-wrapper');
-
- // attachment
- this.attach_wrapper = $a(this.wrapper, 'div');
-
- // no attachments if file is unsaved
- if(this.frm.doc.__islocal) {
- this.attach_wrapper.innerHTML = '
Attachments can be \
- uploaded after saving
';
- return;
- }
-
- // no of attachments
- var n = this.frm.doc.file_list ? this.frm.doc.file_list.split('\n').length : 0;
-
- // button if the number of attachments is less than max
- if(n < this.frm.meta.max_attachments || !this.frm.meta.max_attachments) {
- this.btn = $btn($a(this.wrapper, 'div'), 'Add new attachment',
- function() { me.add_attachment() });
- }
-
- // render
- this.render();
-
- }
-
- // create Attachment objects from
- // the file_list
- this.render = function() {
- // clear exisitng
- this.attach_wrapper.innerHTML = ''
-
- var doc = locals[me.frm.doctype][me.frm.docname];
- var fl = doc.file_list ? doc.file_list.split('\n') : [];
-
- // add attachment objects
- for(var i=0; i\
+ \
+ \
+ ').appendTo(this.parent);
+ this.$list = this.wrapper.find(".alert-list");
+
+ this.parent.find(".btn").click(function() {
+ me.new_attachment();
+ })
+ },
+ max_reached: function() {
+ // no of attachments
+ var n = this.frm.doc.file_list ? this.frm.doc.file_list.split('\n').length : 0;
+
+ // button if the number of attachments is less than max
+ if(n < this.frm.meta.max_attachments || !this.frm.meta.max_attachments) {
+ return false;
+ }
+ return true;
+ },
+ refresh: function() {
+ if(this.frm.doc.__islocal || !this.frm.meta.allow_attach) {
+ this.parent.toggle(false);
+ return;
+ }
+ this.parent.toggle(true);
+ this.parent.find(".btn").toggle(!this.max_reached())
+
+ this.$list.empty();
+
+ var fl = this.get_filelist();
+
+ // add attachment objects
+ for(var i=0; i\
+ %(filename)s×\
+ ', {
+ filename: filename,
+ href: wn.utils.get_file_link(filename)
+ }))
+ .appendTo(this.$list)
+ .find(".close")
+ .data("fileid", fileid)
+ .click(function() {
+ var yn = confirm("Are you sure you want to delete the attachment?");
+ if(!yn) return;
+
+ var data = $(this).data("fileid");
+ wn.call({
+ method: 'webnotes.widgets.form.utils.remove_attach',
+ args: {
+ 'fid': data,
+ dt: me.frm.doctype,
+ dn: me.frm.docname
+ },
+ callback: function(r,rt) {
+ me.frm.doc.modified = r.message;
+ me.remove_fileid(data);
+ me.frm.refresh();
+ }
+ });
+ return false;
+ });
+ },
+ new_attachment: function() {
+ if(!this.dialog) {
+ this.dialog = new wn.ui.Dialog({
+ title:'Upload Attachment',
+ width: 400
+ })
+ $y(this.dialog.body, {margin:'13px'})
+ this.dialog.make();
+ }
+ this.dialog.body.innerHTML = '';
+ this.dialog.show();
+
+ wn.upload.make({
+ parent: this.dialog.body,
+ args: {
+ from_form: 1,
+ doctype: this.frm.doctype,
+ docname: this.frm.docname
+ },
+ callback: wn.ui.form.file_upload_done
+ });
+
+ },
+ remove_fileid: function(fileid) {
+ this.frm.doc.file_list = $.map(this.get_filelist(), function(f) {
+ if(f.split(',')[1]!=fileid) return f;
+ }).join('\n');
+ }
+})
+
+
+// this function will be called after the upload is done
+// from webnotes.utils.file_manager
+wn.ui.form.file_upload_done = function(doctype, docname, fileid, filename, at_id, new_timestamp) {
+
+ // add to file_list
+ var doc = locals[doctype][docname];
+ if(doc.file_list) {
+ var fl = doc.file_list.split('\n')
+ fl.push(filename + ',' + fileid)
+ doc.file_list = fl.join('\n');
+ }
+ else
+ doc.file_list = filename + ',' + fileid;
+
+ // update timestamp
+ doc.modified = new_timestamp;
+
+ // update file_list
+ var frm = wn.views.formview[doctype].frm;
+ frm.attachments.dialog.hide();
+ msgprint('File Uploaded Sucessfully.');
+ frm.refresh();
+}
diff --git a/public/js/wn/misc/user.js b/public/js/wn/misc/user.js
index 79cc58e2f4..6848c32d72 100644
--- a/public/js/wn/misc/user.js
+++ b/public/js/wn/misc/user.js
@@ -15,7 +15,7 @@ wn.user_info = function(uid) {
}
wn.avatar = function(user, large, title) {
- var image = wn.user_info(user).image;
+ var image = wn.utils.get_file_link(wn.user_info(user).image);
var to_size = large ? 72 : 30;
if(!title) title = wn.user_info(user).fullname;
diff --git a/public/js/wn/misc/utils.js b/public/js/wn/misc/utils.js
index 43a22c501f..dc49440ce9 100644
--- a/public/js/wn/misc/utils.js
+++ b/public/js/wn/misc/utils.js
@@ -1,6 +1,14 @@
wn.provide('wn.utils');
wn.utils = {
+ get_file_link: function(filename) {
+ return wn.utils.is_url(filename) || (filename.indexOf("images/")!=-1)
+ ? filename : 'files/' + filename;
+ },
+ is_url: function(txt) {
+ return txt.toLowerCase().substr(0,7)=='http://'
+ || txt.toLowerCase().substr(0,8)=='https://'
+ },
filter_dict: function(dict, filters) {
var ret = [];
if(typeof filters=='string') {
diff --git a/public/js/wn/upload.js b/public/js/wn/upload.js
index 6b9c2743cd..561bf7c124 100644
--- a/public/js/wn/upload.js
+++ b/public/js/wn/upload.js
@@ -6,8 +6,11 @@ wn.upload = {
style="width:0px; height:0px; border:0px">\
', {
id: id,
action: wn.request.url
diff --git a/public/js/wn/views/listview.js b/public/js/wn/views/listview.js
index 4132d315cf..2be5c6aa1c 100644
--- a/public/js/wn/views/listview.js
+++ b/public/js/wn/views/listview.js
@@ -42,15 +42,12 @@ wn.views.ListView = Class.extend({
$(parent).append(repl('%(name)s', data));
}
else if(opts.content=='avatar') {
- $(parent).append(repl('
',
- data));
+ $(parent).append(wn.avatar(data.owner, false, "Created by: "
+ + wn.user_info(data.owner).fullname));
}
else if(opts.content=='avatar_modified') {
- $(parent).append(repl('\
-
',
- data));
+ $(parent).append(wn.avatar(data.modified_by, false, "Modified by: "
+ + wn.user_info(data.modified_by).fullname));
}
else if(opts.content=='check') {
$(parent).append('');
@@ -106,12 +103,6 @@ wn.views.ListView = Class.extend({
});
},
prepare_data: function(data) {
- data.fullname = wn.user_info(data.owner).fullname;
- data.avatar = wn.user_info(data.owner).image;
-
- data.fullname_modified = wn.user_info(data.modified_by).fullname;
- data.avatar_modified = wn.user_info(data.modified_by).image;
-
if(data.modified)
this.prepare_when(data, data.modified);
diff --git a/webnotes/boot.py b/webnotes/boot.py
index ecbd857355..2504330101 100644
--- a/webnotes/boot.py
+++ b/webnotes/boot.py
@@ -87,7 +87,7 @@ def get_fullnames():
if not r[2]:
r[2] = 'lib/images/ui/avatar.png'
else:
- r[2] = 'files/' + r[2]
+ r[2] = r[2]
d[r[0]]= {'fullname': r[1], 'image': r[2], 'gender': r[3],
'email': r[4] or r[0]}
diff --git a/webnotes/utils/__init__.py b/webnotes/utils/__init__.py
index 941c76c045..0794cdfc58 100644
--- a/webnotes/utils/__init__.py
+++ b/webnotes/utils/__init__.py
@@ -153,10 +153,11 @@ def getdate(string_date):
if " " in string_date:
string_date = string_date.split(" ")[0]
- try:
+ try:
return datetime.datetime.strptime(string_date, "%Y-%m-%d").date()
except ValueError, e:
- return ""
+ webnotes.msgprint("Cannot understand date - '%s'" % \
+ (string_date,), raise_exception=1)
def add_to_date(date, years=0, months=0, days=0):
"""Adds `days` to the given date"""
diff --git a/webnotes/utils/file_manager.py b/webnotes/utils/file_manager.py
index 6fb82423dd..83ad554fa4 100644
--- a/webnotes/utils/file_manager.py
+++ b/webnotes/utils/file_manager.py
@@ -26,23 +26,27 @@ import os, conf
def upload():
# get record details
- dt = webnotes.form_dict.get('doctype')
- dn = webnotes.form_dict.get('docname')
- at_id = webnotes.form_dict.get('at_id')
-
- webnotes.response['type'] = 'iframe'
+ dt = webnotes.form_dict.doctype
+ dn = webnotes.form_dict.docname
+ at_id = webnotes.form_dict.at_id
+ file_url = webnotes.form_dict.file_url
filename = webnotes.form['filedata'].filename
- if not filename:
+
+ webnotes.response['type'] = 'iframe'
+ if not filename and not file_url:
webnotes.response['result'] = """
""" % dt
return
# save
- fid, fname = save_uploaded()
-
+ if filename:
+ fid, fname = save_uploaded()
+ elif file_url:
+ fid, fname = save_url(file_url)
+
# save it in the form
updated = False
if fid:
@@ -53,7 +57,7 @@ def upload():
# with the new modified timestamp
webnotes.response['result'] = """
""" % {
@@ -65,22 +69,85 @@ window.parent.wn.views.formview['%(dt)s'].frm.show_doc('%(dn)s');
'mod': webnotes.conn.get_value(dt, dn, 'modified')
}
-# -------------------------------------------------------
+def save_uploaded():
+ webnotes.response['type'] = 'iframe'
+ fname, content = get_uploaded_content()
+ if content:
+ fid = save_file(fname, content)
+ return fid, fname
+ else:
+ return None, fname
+
+def save_url(file_url):
+ f = webnotes.doc("File Data")
+ f.file_url = file_url
+ f.file_name = file_url.split('/')[-1]
+ f.save(new=1)
+ return f.name, file_url
+
+def get_uploaded_content():
+ # should not be unicode when reading a file, hence using webnotes.form
+ if 'filedata' in webnotes.form:
+ i = webnotes.form['filedata']
+ webnotes.uploaded_filename, webnotes.uploaded_content = i.filename, i.file.read()
+ return webnotes.uploaded_filename, webnotes.uploaded_content
+ else:
+ webnotes.msgprint('No File');
+ return None, None
+
+def save_file(fname, content, module=None):
+ from webnotes.model.doc import Document
+ from filecmp import cmp
+
+ check_max_file_size(content)
+ new_fname = write_file(content)
+
+ # some browsers return the full path
+ if '\\' in fname:
+ fname = fname.split('\\')[-1]
+ if '/' in fname:
+ fname = fname.split('/')[-1]
+
+ # we use - for versions, so remove them from the name!
+ fname = fname.replace('-', '')
+
+ fpath = os.path.join(get_files_path(), fname)
+ if os.path.exists(fpath) and cmp(fpath, new_fname):
+ # remove new file, already exists!
+ os.remove(new_fname)
+ return fname
+ else:
+ # generate the ID (?)
+ f = Document('File Data')
+ f.file_name = fname
+ f.save(1)
+ # rename new file
+ os.rename(new_fname, os.path.join(get_files_path(), f.name))
+ return f.name
+
+def check_max_file_size(content):
+ max_file_size = getattr(conf, 'max_file_size', 1000000)
+
+ if len(content) > max_file_size:
+ raise Exception, 'Maximum File Limit (%s MB) Crossed' % (int(max_file_size / 1000000))
+
+def write_file(content):
+ """write file to disk with a random name (to compare)"""
+ # create account folder (if not exists)
+ webnotes.create_folder(get_files_path())
+ fname = os.path.join(get_files_path(), webnotes.generate_hash())
+
+ # write the file
+ with open(fname, 'w+') as f:
+ f.write(content)
+
+ return fname
def add_file_list(dt, dn, fname, fid):
- """
- udpate file_list attribute of the record
- """
fl = webnotes.conn.get_value(dt, dn, 'file_list') or ''
- if fl:
- fl += '\n'
-
- # add new file id
+ if fl: fl += '\n'
fl += fname + ',' + fid
-
- # save
webnotes.conn.set_value(dt, dn, 'file_list', fl)
-
return True
def remove_all(dt, dn):
@@ -111,87 +178,6 @@ def remove_file(dt, dn, fid):
# return the new timestamp
return webnotes.conn.get_value(dt, dn, 'modified')
-def make_thumbnail(blob, size):
- from PIL import Image
- from cStringIO import StringIO
-
- fobj = StringIO(blob)
- image = Image.open(fobj)
- image.thumbnail((tn,tn*2), Image.ANTIALIAS)
- outfile = cStringIO.StringIO()
- image.save(outfile, 'JPEG')
- outfile.seek(0)
- fcontent = outfile.read()
-
- return fcontent
-
-def get_uploaded_content():
- # should not be unicode when reading a file, hence using webnotes.form
- if 'filedata' in webnotes.form:
- i = webnotes.form['filedata']
- webnotes.uploaded_filename, webnotes.uploaded_content = i.filename, i.file.read()
- return webnotes.uploaded_filename, webnotes.uploaded_content
- else:
- webnotes.msgprint('No File');
- return None, None
-
-def save_uploaded():
- webnotes.response['type'] = 'iframe'
- fname, content = get_uploaded_content()
- if content:
- fid = save_file(fname, content)
- return fid, fname
- else:
- return None, fname
-
-def save_file(fname, content, module=None):
- from webnotes.model.doc import Document
- from filecmp import cmp
-
- check_max_file_size(content)
- new_fname = write_file(content)
-
- # some browsers return the full path
- if '\\' in fname:
- fname = fname.split('\\')[-1]
- if '/' in fname:
- fname = fname.split('/')[-1]
-
- # we use - for versions, so remove them from the name!
- fname = fname.replace('-', '')
-
- fpath = os.path.join(get_files_path(), fname)
- if os.path.exists(fpath) and cmp(fpath, new_fname):
- # remove file, already exists!
- os.remove(new_fname)
- return fname
- else:
- # generate the ID (?)
- f = Document('File Data')
- f.file_name = fname
- f.save(1)
- # rename new file
- os.rename(new_fname, os.path.join(get_files_path(), f.name))
- return f.name
-
-def check_max_file_size(content):
- max_file_size = getattr(conf, 'max_file_size', 1000000)
-
- if len(content) > max_file_size:
- raise Exception, 'Maximum File Limit (%s MB) Crossed' % (int(max_file_size / 1000000))
-
-def write_file(content):
- """write file to disk with a random name"""
- # create account folder (if not exists)
- webnotes.create_folder(get_files_path())
- fname = os.path.join(get_files_path(), webnotes.generate_hash())
-
- # write the file
- with open(fname, 'w+') as f:
- f.write(content)
-
- return fname
-
def get_file_system_name(fname):
# get system name from File Data table
return webnotes.conn.sql("""select name, file_name from `tabFile Data`
@@ -228,4 +214,18 @@ def get_files_path():
import os, conf
files_path = os.path.join(os.path.dirname(os.path.abspath(conf.__file__)),
'public', 'files')
- return files_path
\ No newline at end of file
+ return files_path
+
+def make_thumbnail(blob, size):
+ from PIL import Image
+ from cStringIO import StringIO
+
+ fobj = StringIO(blob)
+ image = Image.open(fobj)
+ image.thumbnail((tn,tn*2), Image.ANTIALIAS)
+ outfile = cStringIO.StringIO()
+ image.save(outfile, 'JPEG')
+ outfile.seek(0)
+ fcontent = outfile.read()
+
+ return fcontent
\ No newline at end of file