diff --git a/frappe/core/doctype/custom_field/custom_field.js b/frappe/core/doctype/custom_field/custom_field.js
index 040cb10616..ec4eea4809 100644
--- a/frappe/core/doctype/custom_field/custom_field.js
+++ b/frappe/core/doctype/custom_field/custom_field.js
@@ -47,9 +47,18 @@ cur_frm.fields_dict['dt'].get_query = function(doc, dt, dn) {
}
cur_frm.cscript.fieldtype = function(doc, dt, dn) {
- if(doc.fieldtype == 'Link') cur_frm.fields_dict['options_help'].disp_area.innerHTML = 'Please enter name of the document you want this field to be linked to in Options.
Eg.: Customer';
- else if(doc.fieldtype == 'Select') cur_frm.fields_dict['options_help'].disp_area.innerHTML = 'Please enter values in Options, with each option on a new line.
Eg.: Field: Country
Options:
China
India
United States
';
- else cur_frm.fields_dict['options_help'].disp_area.innerHTML = '';
+ if(doc.fieldtype == 'Link') {
+ cur_frm.fields_dict['options_help'].disp_area.innerHTML =
+ __('Name of the Document Type (DocType) you want this field to be linked to. e.g. Customer');
+ } else if(doc.fieldtype == 'Select') {
+ cur_frm.fields_dict['options_help'].disp_area.innerHTML =
+ __('Options for select. Each option on a new line. e.g.:
Option 1
Option 2
Option 3
');
+ } else if(doc.fieldtype == 'Dynamic Link') {
+ cur_frm.fields_dict['options_help'].disp_area.innerHTML =
+ __('Fieldname which will be the DocType for this link field.');
+ } else {
+ cur_frm.fields_dict['options_help'].disp_area.innerHTML = '';
+ }
}
diff --git a/frappe/core/doctype/custom_field/custom_field.json b/frappe/core/doctype/custom_field/custom_field.json
index 58be09b1c4..55c404c902 100644
--- a/frappe/core/doctype/custom_field/custom_field.json
+++ b/frappe/core/doctype/custom_field/custom_field.json
@@ -57,7 +57,7 @@
"no_copy": 0,
"oldfieldname": "fieldtype",
"oldfieldtype": "Select",
- "options": "Button\nCheck\nCode\nColumn Break\nCurrency\nData\nDate\nDatetime\nFloat\nHTML\nImage\nInt\nLink\nLong Text\nPassword\nPercent\nRead Only\nSection Break\nSelect\nSmall Text\nTable\nText\nText Editor\nTime",
+ "options": "Button\nCheck\nCode\nColumn Break\nCurrency\nData\nDate\nDatetime\nDynamic Link\nFloat\nHTML\nImage\nInt\nLink\nLong Text\nPassword\nPercent\nRead Only\nSection Break\nSelect\nSmall Text\nTable\nText\nText Editor\nTime",
"permlevel": 0,
"reqd": 1,
"search_index": 0
@@ -257,7 +257,7 @@
],
"icon": "icon-glass",
"idx": 1,
- "modified": "2014-05-26 03:21:02.832530",
+ "modified": "2014-06-20 05:54:17.225853",
"modified_by": "Administrator",
"module": "Core",
"name": "Custom Field",
diff --git a/frappe/core/doctype/docfield/docfield.json b/frappe/core/doctype/docfield/docfield.json
index b68a566d98..b1296d4056 100644
--- a/frappe/core/doctype/docfield/docfield.json
+++ b/frappe/core/doctype/docfield/docfield.json
@@ -34,7 +34,7 @@
"label": "Type",
"oldfieldname": "fieldtype",
"oldfieldtype": "Select",
- "options": "Attach\nButton\nCheck\nCode\nColumn Break\nCurrency\nData\nDate\nDatetime\nFloat\nHTML\nImage\nInt\nLink\nLong Text\nPassword\nPercent\nRead Only\nSection Break\nSelect\nSmall Text\nTable\nText\nText Editor\nTime",
+ "options": "Attach\nButton\nCheck\nCode\nColumn Break\nCurrency\nData\nDate\nDatetime\nDynamic Link\nFloat\nHTML\nImage\nInt\nLink\nLong Text\nPassword\nPercent\nRead Only\nSection Break\nSelect\nSmall Text\nTable\nText\nText Editor\nTime",
"permlevel": 0,
"reqd": 1,
"search_index": 1
@@ -304,7 +304,7 @@
"in_dialog": 1,
"issingle": 0,
"istable": 1,
- "modified": "2014-05-26 03:00:13.705058",
+ "modified": "2014-06-20 05:42:29.975498",
"modified_by": "Administrator",
"module": "Core",
"name": "DocField",
diff --git a/frappe/core/doctype/doctype/doctype.py b/frappe/core/doctype/doctype/doctype.py
index 963c7dbb93..26bdba1ab0 100644
--- a/frappe/core/doctype/doctype/doctype.py
+++ b/frappe/core/doctype/doctype/doctype.py
@@ -11,6 +11,7 @@ from frappe.utils import now, cint
from frappe.model import no_value_fields
from frappe.model.document import Document
from frappe.model.db_schema import type_map
+from frappe.core.doctype.property_setter.property_setter import make_property_setter
class DocType(Document):
def validate(self):
@@ -106,6 +107,29 @@ class DocType(Document):
else:
frappe.db.sql("rename table `tab%s` to `tab%s`" % (old, new))
+ def before_reload(self):
+ if not (self.issingle and self.istable):
+ self.preserve_naming_series_options_in_property_setter()
+
+ def preserve_naming_series_options_in_property_setter(self):
+ """preserve naming_series as property setter if it does not exist"""
+ naming_series = self.get("fields", {"fieldname": "naming_series"})
+
+ if not naming_series:
+ return
+
+ # check if atleast 1 record exists
+ if not (frappe.db.table_exists("tab" + self.name) and frappe.db.sql("select name from `tab{}` limit 1".format(self.name))):
+ return
+
+ existing_property_setter = frappe.db.get_value("Property Setter", {"doc_type": self.name,
+ "property": "options", "field_name": "naming_series"})
+
+ if not existing_property_setter:
+ make_property_setter(self.name, "naming_series", "options", naming_series[0].options, "Text")
+ if naming_series[0].default:
+ make_property_setter(self.name, "naming_series", "default", naming_series[0].default, "Text")
+
def export_doc(self):
from frappe.modules.export_file import export_to_files
export_to_files(record_list=[['DocType', self.name]])
@@ -157,6 +181,7 @@ class DocType(Document):
def validate_fields_for_doctype(doctype):
validate_fields(frappe.get_meta(doctype).get("fields"))
+# this is separate because it is also called via custom field
def validate_fields(fields):
def check_illegal_characters(fieldname):
for c in ['.', ',', ' ', '-', '&', '%', '=', '"', "'", '*', '$',
@@ -200,6 +225,13 @@ def validate_fields(fields):
if d.in_list_view and d.fieldtype!="Image" and (d.fieldtype in no_value_fields):
frappe.throw(_("'In List View' not allowed for type {0} in row {1}").format(d.fieldtype, d.idx))
+ def check_dynamic_link_options(d):
+ if d.fieldtype=="Dynamic Link":
+ doctype_pointer = filter(lambda df: df.fieldname==d.options, fields)
+ if not doctype_pointer or (doctype_pointer[0].fieldtype!="Link") \
+ or (doctype_pointer[0].options!="DocType"):
+ frappe.throw(_("Options 'Dynamic Link' type of field must point to another Link Field with options as 'DocType'"))
+
for d in fields:
if not d.permlevel: d.permlevel = 0
if not d.fieldname:
@@ -208,6 +240,7 @@ def validate_fields(fields):
check_unique_fieldname(d.fieldname)
check_illegal_mandatory(d)
check_link_table_options(d)
+ check_dynamic_link_options(d)
check_hidden_and_mandatory(d)
check_in_list_view(d)
diff --git a/frappe/core/doctype/event/event.json b/frappe/core/doctype/event/event.json
index ec5e6ca3ad..de46143f73 100644
--- a/frappe/core/doctype/event/event.json
+++ b/frappe/core/doctype/event/event.json
@@ -218,24 +218,26 @@
},
{
"fieldname": "ref_type",
- "fieldtype": "Data",
+ "fieldtype": "Link",
"hidden": 0,
"label": "Ref Type",
"no_copy": 0,
"oldfieldname": "ref_type",
"oldfieldtype": "Data",
+ "options": "DocType",
"permlevel": 0,
- "read_only": 1,
+ "read_only": 0,
"search_index": 0
},
{
"fieldname": "ref_name",
- "fieldtype": "Data",
+ "fieldtype": "Dynamic Link",
"hidden": 0,
"label": "Ref Name",
"no_copy": 0,
"oldfieldname": "ref_name",
"oldfieldtype": "Data",
+ "options": "ref_type",
"permlevel": 0,
"read_only": 1,
"search_index": 0
@@ -244,7 +246,7 @@
"icon": "icon-calendar",
"idx": 1,
"in_create": 1,
- "modified": "2014-05-27 03:49:10.612463",
+ "modified": "2014-06-20 06:40:05.415405",
"modified_by": "Administrator",
"module": "Core",
"name": "Event",
diff --git a/frappe/core/doctype/todo/todo.json b/frappe/core/doctype/todo/todo.json
index 1139bf07bb..ec9e27e2b2 100644
--- a/frappe/core/doctype/todo/todo.json
+++ b/frappe/core/doctype/todo/todo.json
@@ -91,13 +91,14 @@
{
"allow_on_submit": 0,
"fieldname": "reference_type",
- "fieldtype": "Data",
+ "fieldtype": "Link",
"hidden": 0,
"in_filter": 0,
"label": "Reference Type",
"no_copy": 0,
"oldfieldname": "reference_type",
"oldfieldtype": "Data",
+ "options": "DocType",
"permlevel": 0,
"print_hide": 0,
"report_hide": 0,
@@ -107,13 +108,14 @@
{
"allow_on_submit": 0,
"fieldname": "reference_name",
- "fieldtype": "Data",
+ "fieldtype": "Dynamic Link",
"hidden": 0,
"in_filter": 0,
"label": "Reference Name",
"no_copy": 0,
"oldfieldname": "reference_name",
"oldfieldtype": "Data",
+ "options": "reference_type",
"permlevel": 0,
"print_hide": 0,
"report_hide": 0,
@@ -158,7 +160,7 @@
"in_dialog": 0,
"issingle": 0,
"max_attachments": 0,
- "modified": "2014-05-27 03:49:21.667888",
+ "modified": "2014-06-20 06:20:11.947183",
"modified_by": "Administrator",
"module": "Core",
"name": "ToDo",
diff --git a/frappe/core/page/user_permissions/user_permissions.js b/frappe/core/page/user_permissions/user_permissions.js
index 893a8731f6..c35c5574b5 100644
--- a/frappe/core/page/user_permissions/user_permissions.js
+++ b/frappe/core/page/user_permissions/user_permissions.js
@@ -77,6 +77,22 @@ frappe.UserPermissions = Class.extend({
options: "[Select]"
});
+ if(user_roles.indexOf("System Manager")!==-1) {
+ me.download = me.wrapper.appframe.add_field({
+ fieldname: "download",
+ label: __("Download"),
+ fieldtype: "Button",
+ icon: "icon-download"
+ });
+
+ me.upload = me.wrapper.appframe.add_field({
+ fieldname: "upload",
+ label: __("Upload"),
+ fieldtype: "Button",
+ icon: "icon-upload"
+ });
+ }
+
// bind change event
$.each(me.filters, function(k, f) {
f.$input.on("change", function() {
@@ -90,9 +106,51 @@ frappe.UserPermissions = Class.extend({
});
me.set_from_route();
+ me.setup_download_upload();
}
});
},
+ setup_download_upload: function() {
+ var me = this;
+ me.download.$input.on("click", function() {
+ window.location.href = frappe.urllib.get_base_url()
+ + "/api/method/frappe.core.page.user_permissions.user_permissions.get_user_permissions_csv";
+ });
+
+ me.upload.$input.on("click", function() {
+ var d = new frappe.ui.Dialog({
+ title: "Upload User Permissions",
+ fields: [
+ {
+ fieldtype:"HTML",
+ options: ''+
+ "- "+__("Upload CSV file containing all user permissions in the same format as Download.")+"
"+
+ "- "+__("Any existing permission will be deleted / overwritten.")+"
"+
+ '
'
+ },
+ {
+ fieldtype:"Attach", fieldname:"attach",
+ }
+ ],
+ primary_action_label: __("Upload and Sync"),
+ primary_action: function() {
+ frappe.call({
+ method:"frappe.core.page.user_permissions.user_permissions.import_user_permissions",
+ args: {
+ filedata: d.fields_dict.attach.get_value()
+ },
+ callback: function(r) {
+ if(!r.exc) {
+ msgprint("Permissions Updated");
+ d.hide();
+ }
+ }
+ });
+ }
+ });
+ d.show();
+ })
+ },
get_link_names: function() {
return this.options.link_fields;
},
diff --git a/frappe/core/page/user_permissions/user_permissions.py b/frappe/core/page/user_permissions/user_permissions.py
index 5ad93f7bff..e4722cc467 100644
--- a/frappe/core/page/user_permissions/user_permissions.py
+++ b/frappe/core/page/user_permissions/user_permissions.py
@@ -7,6 +7,8 @@ from frappe import _
import frappe.defaults
import frappe.permissions
from frappe.core.doctype.user.user import get_system_users
+from frappe.utils.datautils import UnicodeWriter, read_csv_content_from_uploaded_file
+from frappe.defaults import clear_default
@frappe.whitelist()
def get_users_and_links():
@@ -79,3 +81,28 @@ def get_doctypes_for_user_permissions():
return frappe.db.sql_list("""select name from tabDocType
where ifnull(issingle,0)=0 and ifnull(istable,0)=0 {condition}""".format(condition=condition),
tuple(values))
+
+@frappe.whitelist()
+def get_user_permissions_csv():
+ out = [["User Permissions"], ["User", "Document Type", "Value"]]
+ out += [[a.parent, a.defkey, a.defvalue] for a in get_permissions()]
+
+ csv = UnicodeWriter()
+ for row in out:
+ csv.writerow(row)
+
+ frappe.response['result'] = str(csv.getvalue())
+ frappe.response['type'] = 'csv'
+ frappe.response['doctype'] = "User Permissions"
+
+@frappe.whitelist()
+def import_user_permissions():
+ frappe.only_for("System Manager")
+ rows = read_csv_content_from_uploaded_file(ignore_encoding=True)
+ clear_default(parenttype="User Permission")
+
+ if rows[0][0]!="User Permissions" and rows[1][0] != "User":
+ frappe.throw(frappe._("Please upload using the same template as download."))
+
+ for row in rows[2:]:
+ frappe.permissions.add_user_permission(row[1], row[2], row[0])
diff --git a/frappe/database.py b/frappe/database.py
index c082aa0a74..721de5576f 100644
--- a/frappe/database.py
+++ b/frappe/database.py
@@ -485,6 +485,9 @@ class Database:
def table_exists(self, tablename):
return tablename in [d[0] for d in self.sql("show tables")]
+ def a_row_exists(self, doctype):
+ return self.sql("select name from `tab{doctype}` limit 1".format(doctype=doctype))
+
def exists(self, dt, dn=None):
if isinstance(dt, basestring):
if dt!="DocType" and dt==dn:
diff --git a/frappe/defaults.py b/frappe/defaults.py
index 80997e4420..2077e46207 100644
--- a/frappe/defaults.py
+++ b/frappe/defaults.py
@@ -4,6 +4,9 @@
from __future__ import unicode_literals
import frappe
+# Note: DefaultValue records are identified by parenttype
+# __default, __global or 'User Permission'
+
common_keys = ["__default", "__global"]
def set_user_default(key, value, user=None, parenttype=None):
diff --git a/frappe/model/base_document.py b/frappe/model/base_document.py
index 7c84c5e654..fd3d66e001 100644
--- a/frappe/model/base_document.py
+++ b/frappe/model/base_document.py
@@ -264,14 +264,21 @@ class BaseDocument(object):
return "{}: {}".format(_(df.label), docname)
invalid_links = []
- for df in self.meta.get_link_fields():
- doctype = df.options
+ for df in self.meta.get_link_fields() + self.meta.get("fields",
+ {"fieldtype":"Dynamic Link"}):
- if not doctype:
- frappe.throw(_("Options not set for link field {0}").format(df.fieldname))
docname = self.get(df.fieldname)
if docname:
+ if df.fieldtype=="Link":
+ doctype = df.options
+ if not doctype:
+ frappe.throw(_("Options not set for link field {0}").format(df.fieldname))
+ else:
+ doctype = self.get(df.options)
+ if not doctype:
+ frappe.throw(_("{0} must be set first").format(self.meta.get_label(df.options)))
+
# MySQL is case insensitive. Preserve case of the original docname in the Link Field.
value = frappe.db.get_value(doctype, docname)
setattr(self, df.fieldname, value)
diff --git a/frappe/model/db_schema.py b/frappe/model/db_schema.py
index 488f623cea..7f2a013d8c 100644
--- a/frappe/model/db_schema.py
+++ b/frappe/model/db_schema.py
@@ -29,6 +29,7 @@ type_map = {
,'Text': ('text', '')
,'Data': ('varchar', '255')
,'Link': ('varchar', '255')
+ ,'Dynamic Link':('varchar', '255')
,'Password': ('varchar', '255')
,'Select': ('varchar', '255')
,'Read Only': ('varchar', '255')
diff --git a/frappe/model/delete_doc.py b/frappe/model/delete_doc.py
index 56c334f33a..86214cb3fb 100644
--- a/frappe/model/delete_doc.py
+++ b/frappe/model/delete_doc.py
@@ -8,6 +8,7 @@ import frappe.model.meta
import frappe.defaults
from frappe.utils.file_manager import remove_all
from frappe import _
+from rename_doc import dynamic_link_queries
def delete_doc(doctype=None, name=None, force=0, ignore_doctypes=None, for_reload=False, ignore_permissions=False):
"""
@@ -31,7 +32,16 @@ def delete_doc(doctype=None, name=None, force=0, ignore_doctypes=None, for_reloa
remove_all(doctype, name)
if doctype=="DocType":
- if not for_reload:
+ if for_reload:
+
+ try:
+ doc = frappe.get_doc(doctype, name)
+ except frappe.DoesNotExistError:
+ pass
+ else:
+ doc.run_method("before_reload")
+
+ else:
frappe.db.sql("delete from `tabCustom Field` where dt = %s", name)
frappe.db.sql("delete from `tabCustom Script` where dt = %s", name)
frappe.db.sql("delete from `tabProperty Setter` where doc_type = %s", name)
@@ -48,6 +58,7 @@ def delete_doc(doctype=None, name=None, force=0, ignore_doctypes=None, for_reloa
# check if links exist
if not force:
check_if_doc_is_linked(doc)
+ check_if_doc_is_dynamically_linked(doc)
delete_from_table(doctype, name, ignore_doctypes, doc)
@@ -106,3 +117,21 @@ def check_if_doc_is_linked(doc, method="Delete"):
frappe.throw(_("Cannot delete or cancel because {0} {1} is linked with {2} {3}").format(doc.doctype,
doc.name, item.parent or item.name, item.parenttype if item.parent else link_dt),
frappe.LinkExistsError)
+
+def check_if_doc_is_dynamically_linked(doc):
+ for query in dynamic_link_queries:
+ for df in frappe.db.sql(query, as_dict=True):
+ if frappe.get_meta(df.parent).issingle:
+
+ # dynamic link in single doc
+ refdoc = frappe.get_singles_dict(df.parent)
+ if refdoc.get(df.options)==doc.doctype and refdoc.get(df.fieldname)==doc.name:
+ frappe.throw(_("Cannot delete or cancel because {0} {1} is linked with {2} {3}").format(doc.doctype,
+ doc.name, df.parent, ""), frappe.LinkExistsError)
+ else:
+
+ # dynamic link in table
+ for name in frappe.db.sql_list("""select name from `tab{parent}` where
+ {options}=%s and {fieldname}=%s""".format(**df), (doc.doctype, doc.name)):
+ frappe.throw(_("Cannot delete or cancel because {0} {1} is linked with {2} {3}").format(doc.doctype,
+ doc.name, df.parent, name), frappe.LinkExistsError)
diff --git a/frappe/model/document.py b/frappe/model/document.py
index 1ccc9d2aa9..37265cbd7e 100644
--- a/frappe/model/document.py
+++ b/frappe/model/document.py
@@ -159,7 +159,10 @@ class Document(BaseDocument):
self.check_if_latest()
self.set_parent_in_children()
self.run_before_save_methods()
- self._validate()
+
+ if self._action != "cancel":
+ self._validate()
+
if self._action == "update_after_submit":
self.validate_update_after_submit()
@@ -491,7 +494,7 @@ class Document(BaseDocument):
val1 = cint(val1)
val2 = cint(val2)
elif df.fieldtype in ("Data", "Text", "Small Text", "Long Text",
- "Text Editor", "Select", "Link"):
+ "Text Editor", "Select", "Link", "Dynamic Link"):
val1 = cstr(val1)
val2 = cstr(val2)
diff --git a/frappe/model/rename_doc.py b/frappe/model/rename_doc.py
index 5201158d3b..b8a4237da8 100644
--- a/frappe/model/rename_doc.py
+++ b/frappe/model/rename_doc.py
@@ -33,6 +33,8 @@ def rename_doc(doctype, old, new, force=False, merge=False, ignore_permissions=F
link_fields = get_link_fields(doctype)
update_link_field_values(link_fields, old, new, doctype)
+ rename_dynamic_links(doctype, old, new)
+
if doctype=='DocType':
rename_doctype(doctype, old, new, force)
@@ -274,3 +276,27 @@ def update_parenttype_values(old, new):
update `tab%s` set parenttype=%s
where parenttype=%s""" % (doctype, '%s', '%s'),
(new, old))
+
+dynamic_link_queries = [
+ """select parent, fieldname, options from tabDocField where fieldtype='Dynamic Link'""",
+ """select dt as parent, fieldname, options from `tabCustom Field` where fieldtype='Dynamic Link'""",
+]
+
+def rename_dynamic_links(doctype, old, new):
+ for query in dynamic_link_queries:
+ for df in frappe.db.sql(query, as_dict=True):
+
+ # dynamic link in single, just one value to check
+ if frappe.get_meta(df.parent).issingle:
+ refdoc = frappe.get_singles_dict(df.parent)
+ if refdoc.get(df.options)==doctype and refdoc.get(df.fieldname)==old:
+
+ frappe.db.sql("""update tabSingles set value=%s where
+ field=%s and value=%s and doctype=%s""", (new, df.fieldname, old, df.parent))
+ else:
+ # replace for each value where renamed
+ for to_change in frappe.db.sql_list("""select name from `tab{parent}` where
+ {options}=%s and {fieldname}=%s""".format(**df), (doctype, old)):
+
+ frappe.db.sql("""update `tab{parent}` set {fieldname}=%s
+ where name=%s""".format(**df), (new, to_change))
diff --git a/frappe/patches.txt b/frappe/patches.txt
index ad0ae5f54f..ebe3416402 100644
--- a/frappe/patches.txt
+++ b/frappe/patches.txt
@@ -43,3 +43,4 @@ execute:frappe.db.sql("""delete from `tabUserRole` where ifnull(parentfield, '')
frappe.patches.v4_0.remove_user_owner_custom_field
execute:frappe.delete_doc("DocType", "Website Template")
execute:frappe.reload_doc('website', 'doctype', 'website_route') #2014-06-17
+execute:frappe.db.sql("""update `tabProperty Setter` set property_type='Text' where property in ('options', 'default')""") #2014-06-20
diff --git a/frappe/permissions.py b/frappe/permissions.py
index b5165f2024..95208d97a7 100644
--- a/frappe/permissions.py
+++ b/frappe/permissions.py
@@ -37,12 +37,13 @@ def has_permission(doctype, ptype="read", doc=None, verbose=True, user=None):
if not role_permissions.get(ptype):
return False
- if doc and role_permissions["apply_user_permissions"].get(ptype):
+ if doc:
if isinstance(doc, basestring):
doc = frappe.get_doc(meta.name, doc)
- if not user_has_permission(doc, verbose=verbose, user=user):
- return False
+ if role_permissions["apply_user_permissions"].get(ptype):
+ if not user_has_permission(doc, verbose=verbose, user=user):
+ return False
if not has_controller_permissions(doc, ptype, user=user):
return False
diff --git a/frappe/public/js/frappe/form/attachments.js b/frappe/public/js/frappe/form/attachments.js
index 5dbdb62e28..c292416fa3 100644
--- a/frappe/public/js/frappe/form/attachments.js
+++ b/frappe/public/js/frappe/form/attachments.js
@@ -61,7 +61,7 @@ frappe.ui.form.Attachments = Class.extend({
},
add_attachment: function(attachment) {
var file_name = attachment.file_name;
- var file_url = attachment.file_url;
+ var file_url = this.get_file_url(attachment);
var fileid = attachment.name;
if (!file_name) {
file_name = file_url;
@@ -96,6 +96,18 @@ frappe.ui.form.Attachments = Class.extend({
$close.remove();
}
},
+ get_file_url: function(attachment) {
+ var file_url = attachment.file_url;
+ if (!file_url) {
+ if (attachment.file_name.indexOf('files/') === 0) {
+ file_url = '/' + attachment.file_name;
+ }
+ else {
+ file_url = '/files/' + attachment.file_name;
+ }
+ }
+ return encodeURI(file_url);
+ },
remove_attachment_by_filename: function(filename, callback) {
this.remove_attachment(this.get_attachments()[filename], callback);
},
diff --git a/frappe/public/js/frappe/form/comments.js b/frappe/public/js/frappe/form/comments.js
index b981037ad0..265ce50dff 100644
--- a/frappe/public/js/frappe/form/comments.js
+++ b/frappe/public/js/frappe/form/comments.js
@@ -49,7 +49,7 @@ frappe.ui.form.Comments = Class.extend({
c.fullname = frappe.user_info(c.comment_by).fullname;
c.comment = frappe.markdown(c.comment);
- $(repl('
\
+ $(repl('