@@ -46,7 +46,7 @@ def get_data(): | |||
"type": "list" | |||
}, | |||
"File Manager": { | |||
"color": "#95a5a6", | |||
"color": "#905df5", | |||
"doctype": "File", | |||
"icon": "icon-folder-close", | |||
"icon": "octicon octicon-file-directory", | |||
@@ -1,19 +1,21 @@ | |||
frappe.ui.form.on("File", "onload", function(frm) { | |||
if(frappe.utils.is_image_file(frm.doc.file_url)){ | |||
frm.doc.preview = '<div class="img_preview">\ | |||
<img style="max-widht:130px;max-height:130px;" \ | |||
src="'+frm.doc.file_url+'"></img>\ | |||
</div>'; | |||
frm.refresh_field("preview"); | |||
} | |||
}) | |||
frappe.ui.form.on("File", "refresh", function(frm) { | |||
frm.add_custom_button(__('Download'), function(){ | |||
window.open(frm.doc.file_url); | |||
}, "icon-download"); | |||
}) | |||
if(!frm.doc.is_folder) { | |||
frm.add_custom_button(__('Download'), function() { | |||
window.open(frm.doc.file_url); | |||
}, "icon-download"); | |||
} | |||
var wrapper = frm.get_field("preview_html").$wrapper; | |||
var is_viewable = frappe.utils.is_image_file(frm.doc.file_url); | |||
frm.toggle_display("preview", is_viewable); | |||
frm.toggle_display("preview_html", is_viewable); | |||
// frappe.ui.form.on("File", "download", function(frm) { | |||
// window.open(frm.doc.file_url); | |||
// }) | |||
if(is_viewable){ | |||
wrapper.html('<div class="img_preview">\ | |||
<img class="img-responsive" src="'+frm.doc.file_url+'"></img>\ | |||
</div>'); | |||
} else { | |||
wrapper.empty(); | |||
} | |||
}); |
@@ -1,7 +1,7 @@ | |||
{ | |||
"allow_copy": 0, | |||
"allow_import": 1, | |||
"allow_rename": 1, | |||
"allow_rename": 0, | |||
"autoname": "hash", | |||
"creation": "2012-12-12 11:19:22", | |||
"custom": 0, | |||
@@ -24,6 +24,28 @@ | |||
"oldfieldtype": "Data", | |||
"permlevel": 0, | |||
"print_hide": 0, | |||
"read_only": 1, | |||
"report_hide": 0, | |||
"reqd": 0, | |||
"search_index": 0, | |||
"set_only_once": 0, | |||
"unique": 0 | |||
}, | |||
{ | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"fieldname": "preview", | |||
"fieldtype": "Section Break", | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
"in_filter": 0, | |||
"in_list_view": 0, | |||
"label": "Preview", | |||
"no_copy": 0, | |||
"permlevel": 0, | |||
"precision": "", | |||
"print_hide": 0, | |||
"read_only": 0, | |||
"report_hide": 0, | |||
"reqd": 0, | |||
@@ -35,13 +57,34 @@ | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"fieldname": "is_folder", | |||
"fieldtype": "Check", | |||
"fieldname": "preview_html", | |||
"fieldtype": "HTML", | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
"in_filter": 0, | |||
"in_list_view": 0, | |||
"label": "Preview HTML", | |||
"no_copy": 0, | |||
"permlevel": 0, | |||
"precision": "", | |||
"print_hide": 0, | |||
"read_only": 0, | |||
"report_hide": 0, | |||
"reqd": 0, | |||
"search_index": 0, | |||
"set_only_once": 0, | |||
"unique": 0 | |||
}, | |||
{ | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"fieldname": "section_break_5", | |||
"fieldtype": "Section Break", | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
"in_filter": 0, | |||
"in_list_view": 0, | |||
"label": "Is Folder", | |||
"no_copy": 0, | |||
"permlevel": 0, | |||
"precision": "", | |||
@@ -80,14 +123,35 @@ | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"depends_on": "eval:!doc.is_folder", | |||
"fieldname": "file_url", | |||
"fieldtype": "Data", | |||
"hidden": 0, | |||
"fieldname": "is_attachments_folder", | |||
"fieldtype": "Check", | |||
"hidden": 1, | |||
"ignore_user_permissions": 0, | |||
"in_filter": 0, | |||
"in_list_view": 0, | |||
"label": "File URL", | |||
"label": "Is Attachments Folder", | |||
"no_copy": 0, | |||
"permlevel": 0, | |||
"precision": "", | |||
"print_hide": 0, | |||
"read_only": 0, | |||
"report_hide": 0, | |||
"reqd": 0, | |||
"search_index": 0, | |||
"set_only_once": 0, | |||
"unique": 0 | |||
}, | |||
{ | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"fieldname": "file_size", | |||
"fieldtype": "Int", | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
"in_filter": 0, | |||
"in_list_view": 1, | |||
"label": "File Size", | |||
"no_copy": 0, | |||
"permlevel": 0, | |||
"print_hide": 0, | |||
@@ -119,13 +183,35 @@ | |||
"set_only_once": 0, | |||
"unique": 0 | |||
}, | |||
{ | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"depends_on": "eval:!doc.is_folder", | |||
"fieldname": "file_url", | |||
"fieldtype": "Data", | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
"in_filter": 0, | |||
"in_list_view": 0, | |||
"label": "File URL", | |||
"no_copy": 0, | |||
"permlevel": 0, | |||
"print_hide": 0, | |||
"read_only": 1, | |||
"report_hide": 0, | |||
"reqd": 0, | |||
"search_index": 0, | |||
"set_only_once": 0, | |||
"unique": 0 | |||
}, | |||
{ | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"fieldname": "folder", | |||
"fieldtype": "Link", | |||
"hidden": 0, | |||
"hidden": 1, | |||
"ignore_user_permissions": 0, | |||
"in_filter": 0, | |||
"in_list_view": 0, | |||
@@ -135,7 +221,7 @@ | |||
"permlevel": 0, | |||
"precision": "", | |||
"print_hide": 0, | |||
"read_only": 0, | |||
"read_only": 1, | |||
"report_hide": 0, | |||
"reqd": 0, | |||
"search_index": 0, | |||
@@ -146,15 +232,16 @@ | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"fieldname": "file_size", | |||
"fieldtype": "Int", | |||
"fieldname": "is_folder", | |||
"fieldtype": "Check", | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
"in_filter": 0, | |||
"in_list_view": 1, | |||
"label": "File Size", | |||
"in_list_view": 0, | |||
"label": "Is Folder", | |||
"no_copy": 0, | |||
"permlevel": 0, | |||
"precision": "", | |||
"print_hide": 0, | |||
"read_only": 1, | |||
"report_hide": 0, | |||
@@ -167,6 +254,7 @@ | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"depends_on": "eval:!doc.is_folder", | |||
"fieldname": "section_break_8", | |||
"fieldtype": "Section Break", | |||
"hidden": 0, | |||
@@ -345,7 +433,7 @@ | |||
"is_submittable": 0, | |||
"issingle": 0, | |||
"istable": 0, | |||
"modified": "2015-09-08 15:57:09.103049", | |||
"modified": "2015-09-18 06:22:10.902847", | |||
"modified_by": "Administrator", | |||
"module": "Core", | |||
"name": "File", | |||
@@ -370,6 +458,26 @@ | |||
"share": 1, | |||
"submit": 0, | |||
"write": 1 | |||
}, | |||
{ | |||
"amend": 0, | |||
"apply_user_permissions": 0, | |||
"cancel": 0, | |||
"create": 1, | |||
"delete": 1, | |||
"email": 1, | |||
"export": 1, | |||
"if_owner": 1, | |||
"import": 0, | |||
"permlevel": 0, | |||
"print": 1, | |||
"read": 1, | |||
"report": 1, | |||
"role": "All", | |||
"set_user_permissions": 0, | |||
"share": 1, | |||
"submit": 0, | |||
"write": 1 | |||
} | |||
], | |||
"read_only": 0, | |||
@@ -30,7 +30,7 @@ class File(NestedSet): | |||
path = get_breadcrumbs(self.folder) | |||
folder_name = frappe.get_value("File", self.folder, "file_name") | |||
return "/".join([d.file_name for d in path] + [folder_name, self.file_name]) | |||
def set_name(self): | |||
"""Set name for folder""" | |||
if self.is_folder: | |||
@@ -44,14 +44,14 @@ class File(NestedSet): | |||
def after_insert(self): | |||
self.update_parent_folder_size() | |||
def after_rename(self, olddn, newdn, merge=False): | |||
for successor in self.get_successor(): | |||
setup_folder_path(successor, self.name) | |||
def get_successor(self): | |||
return frappe.db.sql_list("select name from tabFile where folder='%s'"%self.name) or [] | |||
def validate(self): | |||
self.validate_duplicate_entry() | |||
self.validate_folder() | |||
@@ -83,52 +83,7 @@ class File(NestedSet): | |||
def set_folder_name(self): | |||
"""Make parent folders if not exists based on reference doctype and name""" | |||
if self.attached_to_doctype and not self.folder: | |||
self.folder = self.get_parent_folder_name() | |||
def get_parent_folder_name(self): | |||
"""Returns parent folder name. If not exists, then make""" | |||
doctype_folder_name = self.get_doctype_folder_name() | |||
parent_folder_name = frappe.db.get_value("File", {"file_name": self.attached_to_name, | |||
"is_folder": 1, "folder": doctype_folder_name}) | |||
return self.make_folder(parent_folder_name, doctype_folder_name, | |||
self.attached_to_name) | |||
def get_doctype_folder_name(self): | |||
"""Returns doctype folder name. If not exists, then make""" | |||
module_folder_name = self.get_module_folder_name() | |||
doctype_folder_name = frappe.db.get_value("File", {"file_name": self.attached_to_doctype, | |||
"is_folder": 1, "folder": module_folder_name}) | |||
return self.make_folder(doctype_folder_name, module_folder_name, | |||
_(self.attached_to_doctype, frappe.db.get_default("lang"))) | |||
def get_module_folder_name(self): | |||
"""Returns module folder name. If not exists, then make""" | |||
if self.attached_to_doctype: | |||
module = frappe.db.get_value("DocType", self.attached_to_doctype, "module") | |||
home_folder_name = frappe.db.get_value("File", {"is_home_folder": 1}) | |||
module_folder_name = frappe.db.get_value("File", {"file_name": module, | |||
"is_folder": 1, "folder": home_folder_name}) | |||
return self.make_folder(module_folder_name, home_folder_name, _(module, | |||
frappe.db.get_default("lang"))) | |||
def make_folder(self, name, folder, file_name): | |||
if not name: | |||
# parent folder | |||
file = frappe.get_doc({ | |||
"doctype": "File", | |||
"is_folder": 1, | |||
"file_name": file_name, | |||
"folder": folder | |||
}).insert() | |||
name = file.name | |||
return name | |||
self.folder = frappe.db.get_value("File", {"is_attachments_folder": 1}) | |||
def validate_folder(self): | |||
if not self.is_home_folder and not self.folder and \ | |||
@@ -188,13 +143,21 @@ def on_doctype_update(): | |||
frappe.db.add_index("File", ["attached_to_doctype", "attached_to_name"]) | |||
def make_home_folder(): | |||
frappe.get_doc({ | |||
home = frappe.get_doc({ | |||
"doctype": "File", | |||
"is_folder": 1, | |||
"is_home_folder": 1, | |||
"file_name": _("Home") | |||
}).insert() | |||
frappe.get_doc({ | |||
"doctype": "File", | |||
"folder": home.name, | |||
"is_folder": 1, | |||
"is_attachments_folder": 1, | |||
"file_name": _("Attachments") | |||
}).insert() | |||
@frappe.whitelist() | |||
def get_breadcrumbs(folder): | |||
"""returns name, file_name of parent folder""" | |||
@@ -221,11 +184,11 @@ def move_file(file_list, new_parent, old_parent): | |||
frappe.get_doc("File", new_parent).save() | |||
return "File(s) has been moved successfully!!" | |||
def setup_folder_path(filename, new_parent): | |||
file = frappe.get_doc("File", filename) | |||
file.folder = new_parent | |||
file.save() | |||
if file.is_folder: | |||
frappe.rename_doc("File", file.name, file.get_name_based_on_parent_folder()) | |||
frappe.rename_doc("File", file.name, file.get_name_based_on_parent_folder()) |
@@ -32,7 +32,7 @@ frappe.listview_settings['File'] = { | |||
doclist.breadcrumb = $('<ol class="breadcrumb for-file-list"></ol>') | |||
.insertBefore(doclist.filter_area); | |||
doclist.listview.settings.setup_new_folder(doclist); | |||
doclist.listview.settings.setup_menu(doclist); | |||
doclist.listview.settings.setup_dragdrop(doclist); | |||
doclist.$page.on("click", ".list-delete", function(event) { | |||
@@ -52,7 +52,7 @@ frappe.listview_settings['File'] = { | |||
}); | |||
}); | |||
}, | |||
setup_new_folder: function(doclist) { | |||
setup_menu: function(doclist) { | |||
doclist.page.add_menu_item(__("New Folder"), function() { | |||
var d = frappe.prompt(__("Name"), function(values) { | |||
if((values.value.indexOf("/") > -1)){ | |||
@@ -70,6 +70,10 @@ frappe.listview_settings['File'] = { | |||
}) | |||
}, __('Enter folder name'), __("Create")); | |||
}); | |||
doclist.page.add_menu_item(__("Edit Folder"), function() { | |||
frappe.set_route("Form", "File", doclist.current_folder); | |||
}); | |||
}, | |||
setup_dragdrop: function(doclist) { | |||
$(doclist.$page).on('dragenter dragover', false) | |||
@@ -153,7 +157,9 @@ frappe.listview_settings['File'] = { | |||
doclist.filter_list.add_filter("File", "folder", "=", doclist.current_folder, true); | |||
doclist.dirty = true; | |||
doclist.fresh = false; | |||
doclist.page.set_title(doclist.current_folder_name); | |||
frappe.utils.set_title(doclist.current_folder_name); | |||
}, | |||
set_primary_action:function(doclist){ | |||
@@ -165,7 +171,6 @@ frappe.listview_settings['File'] = { | |||
"from_form": 1 | |||
}, | |||
callback: function() { | |||
console.log('here') | |||
doclist.refresh(); | |||
} | |||
}); | |||
@@ -7,7 +7,7 @@ def execute(): | |||
frappe.rename_doc("DocType", "File Data", "File") | |||
frappe.reload_doctype("File") | |||
# DELETE THIS | |||
# TODO: DELETE THIS | |||
frappe.db.sql("""delete from tabFile where is_folder=1""") | |||
frappe.db.sql("""update tabFile set folder=null""") | |||
@@ -52,6 +52,7 @@ def has_permission(doctype, ptype="read", doc=None, verbose=False, user=None): | |||
if doc_name in shared: | |||
if verbose: print "Shared" | |||
if ptype in ("read", "write", "share") or meta.permissions[0].get(ptype): | |||
if verbose: print "Is shared" | |||
return True | |||
elif shared: | |||
@@ -60,6 +61,7 @@ def has_permission(doctype, ptype="read", doc=None, verbose=False, user=None): | |||
if verbose: print "Has a shared document" | |||
return True | |||
if verbose: print "Not Shared" | |||
return False | |||
role_permissions = get_role_permissions(meta, user=user, verbose=verbose) | |||
@@ -67,28 +69,40 @@ def has_permission(doctype, ptype="read", doc=None, verbose=False, user=None): | |||
if not role_permissions.get(ptype): | |||
return false_if_not_shared() | |||
perm = True | |||
if doc: | |||
if isinstance(doc, basestring): | |||
doc = frappe.get_doc(meta.name, doc) | |||
# if owner match, then return True | |||
if doc.owner == frappe.session.user and role_permissions["if_owner"].get(ptype) and ptype!="create": | |||
return True | |||
owner_perm = user_perm = controller_perm = None | |||
if role_permissions["if_owner"].get(ptype) and ptype!="create": | |||
owner_perm = doc.owner == frappe.session.user | |||
if verbose: print "Owner permission: {0}".format(owner_perm) | |||
# check if user permission | |||
if role_permissions["apply_user_permissions"].get(ptype): | |||
if not user_has_permission(doc, verbose=verbose, user=user, | |||
user_permission_doctypes=role_permissions.get("user_permission_doctypes", {}).get(ptype) or []): | |||
if verbose: print "No user permission" | |||
return false_if_not_shared() | |||
if not has_controller_permissions(doc, ptype, user=user): | |||
if verbose: print "No controller permission" | |||
return false_if_not_shared() | |||
if verbose: | |||
print "Has Role" | |||
return True | |||
if not owner_perm and role_permissions["apply_user_permissions"].get(ptype): | |||
user_perm = user_has_permission(doc, verbose=verbose, user=user, | |||
user_permission_doctypes=role_permissions.get("user_permission_doctypes", {}).get(ptype) or []) | |||
if verbose: print "User permission: {0}".format(user_perm) | |||
if not owner_perm and not user_perm: | |||
controller_perm = has_controller_permissions(doc, ptype, user=user) | |||
if verbose: print "Controller permission: {0}".format(controller_perm) | |||
# permission true if any one condition is explicitly True or all permissions are undefined (None) | |||
perm = any([owner_perm, user_perm, controller_perm]) or \ | |||
all([owner_perm==None, user_perm==None, controller_perm==None]) | |||
if not perm: | |||
perm = false_if_not_shared() | |||
if verbose: print "Final Permission: {0}".format(perm) | |||
return perm | |||
def get_doc_permissions(doc, verbose=False, user=None): | |||
"""Returns a dict of evaluated permissions for given `doc` like `{"read":1, "write":1}`""" | |||
@@ -271,9 +285,15 @@ def user_has_permission(doc, verbose=True, user=None, user_permission_doctypes=N | |||
return _user_has_permission | |||
def has_controller_permissions(doc, ptype, user=None): | |||
"""Returns controller permissions if defined. None if not defined""" | |||
if not user: user = frappe.session.user | |||
for method in frappe.get_hooks("has_permission").get(doc.doctype, []): | |||
methods = frappe.get_hooks("has_permission").get(doc.doctype, []) | |||
if not methods: | |||
return None | |||
for method in methods: | |||
if not frappe.call(frappe.get_attr(method), doc=doc, ptype=ptype, user=user): | |||
return False | |||
@@ -60,6 +60,20 @@ $.extend(frappe.perm, { | |||
}); | |||
} | |||
// if owner | |||
if(!$.isEmptyObject(perm[0].if_owner)) { | |||
if(doc.owner===user) { | |||
$.extend(perm[0], perm[0].if_owner); | |||
} else { | |||
// not owner, remove permissions | |||
$.each(perm[0].if_owner, function(ptype, value) { | |||
if(perm[0].if_owner[ptype]) { | |||
perm[0][ptype] = 0 | |||
} | |||
}) | |||
} | |||
} | |||
// apply permissions from shared | |||
if(docinfo.shared) { | |||
for(var i=0; i<docinfo.shared; i++) { | |||
@@ -78,6 +92,7 @@ $.extend(frappe.perm, { | |||
} | |||
} | |||
} | |||
} | |||
if(frappe.model.can_read(doctype) && !perm[0].read) { | |||
@@ -131,10 +146,6 @@ $.extend(frappe.perm, { | |||
}); | |||
} | |||
} | |||
if (permlevel===0 && p["if_owner"]) { | |||
perm[0]["if_owner"] = 1; | |||
} | |||
} | |||
}); | |||
@@ -4,7 +4,9 @@ | |||
frappe.breadcrumbs = { | |||
all: {}, | |||
preferred: {}, | |||
preferred: { | |||
"File": "" | |||
}, | |||
set_doctype_module: function(doctype, module) { | |||
localStorage["preferred_breadcrumbs:" + doctype] = module; | |||
@@ -33,7 +35,7 @@ frappe.breadcrumbs = { | |||
if(from_module) { | |||
breadcrumbs.module = from_module; | |||
} else if(frappe.breadcrumbs.preferred[breadcrumbs.doctype]) { | |||
} else if(frappe.breadcrumbs.preferred[breadcrumbs.doctype]!==undefined) { | |||
// get preferred module for breadcrumbs | |||
breadcrumbs.module = frappe.breadcrumbs.preferred[breadcrumbs.doctype]; | |||
} | |||
@@ -60,8 +62,9 @@ frappe.breadcrumbs = { | |||
if(breadcrumbs.doctype==="User" && frappe.user.modules.indexOf("Setup")===-1) { | |||
// no user listview for non-system managers | |||
} else { | |||
$(repl('<li><a href="#List/%(doctype)s">%(label)s</a></li>', | |||
{doctype: breadcrumbs.doctype, label: __(breadcrumbs.doctype)})) | |||
route = (cur_frm && cur_frm.list_route) || ("List/" + breadcrumbs.doctype) | |||
$(repl('<li><a href="#%(route)s">%(label)s</a></li>', | |||
{route: route, label: __(breadcrumbs.doctype)})) | |||
.appendTo($breadcrumbs); | |||
} | |||
} | |||