Kaynağa Gözat

[file-manager] fixed breadcrumbs and routing

version-14
Rushabh Mehta 10 yıl önce
ebeveyn
işleme
9fbd12f5af
15 değiştirilmiş dosya ile 250 ekleme ve 108 silme
  1. +18
    -1
      frappe/__init__.py
  2. +88
    -23
      frappe/core/doctype/file/file.json
  3. +43
    -25
      frappe/core/doctype/file/file.py
  4. +28
    -27
      frappe/core/doctype/file/file_list.js
  5. +3
    -2
      frappe/data/Framework.sql
  6. +11
    -7
      frappe/desk/search.py
  7. +4
    -0
      frappe/model/document.py
  8. +5
    -2
      frappe/patches/v6_1/rename_file_data.py
  9. +6
    -1
      frappe/public/css/desk.css
  10. +22
    -11
      frappe/public/js/frappe/list/doclistview.js
  11. +1
    -1
      frappe/public/js/frappe/ui/filters/filters.js
  12. +1
    -1
      frappe/public/js/frappe/ui/toolbar/awesome_bar.js
  13. +10
    -6
      frappe/public/js/frappe/views/factory.js
  14. +7
    -1
      frappe/public/less/desk.less
  15. +3
    -0
      frappe/utils/install.py

+ 18
- 1
frappe/__init__.py Dosyayı Görüntüle

@@ -38,8 +38,11 @@ class _dict(dict):
def copy(self):
return _dict(dict(self).copy())

def _(msg):
def _(msg, lang=None):
"""Returns translated string in current lang, if exists."""
if not lang:
lang = local.lang

if local.lang == "en":
return msg

@@ -905,6 +908,20 @@ def get_all(doctype, *args, **kwargs):
kwargs["limit_page_length"] = 0
return get_list(doctype, *args, **kwargs)

def get_value(*args, **kwargs):
"""Returns a document property or list of properties.

Alias for `frappe.db.get_value`

:param doctype: DocType name.
:param filters: Filters like `{"x":"y"}` or name of the document. `None` if Single DocType.
:param fieldname: Column name.
:param ignore: Don't raise exception if table, column is missing.
:param as_dict: Return values as dict.
:param debug: Print query in error log.
"""
return db.get_value(*args, **kwargs)

def add_version(doc):
"""Insert a new **Version** of the given document.
A **Version** is a JSON dump of the current document state."""


+ 88
- 23
frappe/core/doctype/file/file.json Dosyayı Görüntüle

@@ -8,6 +8,29 @@
"docstatus": 0,
"doctype": "DocType",
"fields": [
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "file_name",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "File Name",
"no_copy": 0,
"oldfieldname": "file_name",
"oldfieldtype": "Data",
"permlevel": 0,
"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,
@@ -34,9 +57,10 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"depends_on": "",
"fieldname": "is_home_folder",
"fieldtype": "Check",
"hidden": 0,
"hidden": 1,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
@@ -52,6 +76,49 @@
"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": "column_break_5",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"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,
@@ -79,16 +146,14 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "file_name",
"fieldtype": "Data",
"fieldname": "file_size",
"fieldtype": "Int",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "File Name",
"in_list_view": 1,
"label": "File Size",
"no_copy": 0,
"oldfieldname": "file_name",
"oldfieldtype": "Data",
"permlevel": 0,
"print_hide": 0,
"read_only": 1,
@@ -102,17 +167,17 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "file_url",
"fieldtype": "Data",
"fieldname": "section_break_8",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "File URL",
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"read_only": 1,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -145,20 +210,20 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "attached_to_name",
"fieldtype": "Data",
"fieldname": "column_break_10",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Attached To Name",
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"read_only": 1,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
@@ -166,20 +231,20 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "file_size",
"fieldtype": "Int",
"fieldname": "attached_to_name",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "File Size",
"in_list_view": 0,
"label": "Attached To Name",
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"search_index": 1,
"set_only_once": 0,
"unique": 0
},
@@ -275,12 +340,12 @@
"hide_toolbar": 0,
"icon": "icon-file",
"idx": 1,
"in_create": 1,
"in_create": 0,
"in_dialog": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 0,
"modified": "2015-09-02 06:17:57.856863",
"modified": "2015-09-03 05:17:44.827959",
"modified_by": "Administrator",
"module": "Core",
"name": "File",


+ 43
- 25
frappe/core/doctype/file/file.py Dosyayı Görüntüle

@@ -21,6 +21,20 @@ class File(NestedSet):
def before_insert(self):
frappe.local.rollback_observers.append(self)
self.set_folder_name()
self.set_name()

def set_name(self):
"""Set name for folder"""
if self.is_folder:
if self.folder:
path = get_breadcrumbs(self.folder)
folder_name = frappe.get_value("File", self.folder, "file_name")
self.name = "/".join([d.file_name for d in path] + [folder_name, self.file_name])
else:
# home
self.name = self.file_name
else:
self.name = self.file_url

def after_insert(self):
self.update_parent_folder_size()
@@ -32,7 +46,7 @@ class File(NestedSet):

def set_folder_size(self):
"""Set folder size if folder"""
if self.is_folder:
if self.is_folder and not self.is_new():
self.fize_size = self.get_folder_size()

for folder in self.get_ancestors():
@@ -45,33 +59,33 @@ class File(NestedSet):
return frappe.db.sql("""select sum(ifnull(file_size,0))
from tabFile where folder=%s""", folder)[0][0]

def update_parent_folder_size(self):
"""Update size of parent folder"""
if self.folder and not self.is_folder: # it not home
frappe.get_doc("File", self.folder).save()

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 update_parent_folder_size(self):
"""Update size of parent folder"""
if self.folder: # it not home
frappe.get_doc("File", self.folder).save()

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()
parent_folder_name = frappe.db.get_value("File", {"file_name": self.attached_to_doctype,
doctype_folder_name = frappe.db.get_value("File", {"file_name": self.attached_to_doctype,
"is_folder": 1, "folder": module_folder_name})
if not parent_folder_name:
# parent folder
parent_folder = frappe.get_doc({
"doctype": "File",
"is_folder": 1,
"file_name": _(self.attached_to_doctype),
"folder": module_folder_name
}).insert()

parent_folder_name = parent_folder.name

return parent_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"""
@@ -83,18 +97,22 @@ class File(NestedSet):
module_folder_name = frappe.db.get_value("File", {"file_name": module,
"is_folder": 1, "folder": home_folder_name})

if not module_folder_name:
module_folder = frappe.get_doc({
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": _(module),
"folder": home_folder_name
"file_name": file_name,
"folder": folder
}).insert()

module_folder_name = module_folder.name

return module_folder_name
name = file.name

return name

def validate_folder(self):
if not self.is_home_folder and not self.folder and \


+ 28
- 27
frappe/core/doctype/file/file_list.js Dosyayı Görüntüle

@@ -1,14 +1,7 @@
//TODO

// show breadcrumbs
// search bar to add search filter
// back button
// new
// if file, attach
// if folder, set name

frappe.listview_settings['File'] = {
hide_name_column: true,
use_route: true,
add_fields: ["is_folder", "file_name"],
formatters: {
file_size: function(value) {
@@ -32,12 +25,23 @@ frappe.listview_settings['File'] = {
}
},
onload: function(doclist) {
doclist.breadcrumb = $('<ol class="breadcrumb"></ol>')
.insertBefore(doclist.wrapper.find(".show_filters"));
doclist.filter_area = doclist.wrapper.find(".show_filters");
doclist.breadcrumb = $('<ol class="breadcrumb for-file-list"></ol>')
.insertBefore(doclist.filter_area);
},
before_run: function(doclist) {
var name_filter = doclist.filter_list.get_filter("file_name");
if(name_filter) {
doclist.filter_area.removeClass("hide");
doclist.breadcrumb.addClass("hide");
} else {
doclist.filter_area.addClass("hide");
doclist.breadcrumb.removeClass("hide");
}
},
refresh: function(doclist) {
// set folder before querying
var name_filter = doclist.filter_list.get_filter("name");
var name_filter = doclist.filter_list.get_filter("file_name");

var folder_filter = doclist.filter_list.get_filter("folder");
if(folder_filter) {
@@ -46,6 +50,12 @@ frappe.listview_settings['File'] = {

if(name_filter) return;

var route = frappe.get_route();
if(route[2]) {
doclist.current_folder = route.slice(2).join("/");
doclist.current_folder_name = route.slice(-1)[0];
}

if(!doclist.current_folder) {
doclist.current_folder = frappe.boot.home_folder;
doclist.current_folder_name = __("Home");
@@ -58,14 +68,12 @@ frappe.listview_settings['File'] = {
},
post_render_item: function(list, row, data) {
if(data.is_folder) {
$(row).find(".list-id").on("click", function() {
list.doclistview.current_folder = data.name;
list.doclistview.current_folder_name = data.file_name;
list.doclistview.refresh();
return false;
});
$(row).find(".list-id").attr("href", "#List/File/" + data.name);
}
},
set_file_route: function(name) {
frappe.set_route(["List", "File"].concat(decodeURIComponent(name).split("/")));
},
post_render: function(doclist) {
frappe.call({
method: "frappe.core.doctype.file.file.get_breadcrumbs",
@@ -76,16 +84,9 @@ frappe.listview_settings['File'] = {
doclist.breadcrumb.empty();
if(r.message && r.message.length) {
$.each(r.message, function(i, folder) {
$('<li><a href="#">'+ folder.file_name+'</a></li>')
.appendTo(doclist.breadcrumb)
.attr("name", folder.name)
.attr("file_name", folder.file_name)
.on("click", function() {
doclist.current_folder = $(this).attr("name");
doclist.current_folder_name = $(this).attr("file_name");
doclist.refresh();
return false;
});
$('<li><a href="#List/File/'+folder.name+'">'
+ folder.file_name+'</a></li>')
.appendTo(doclist.breadcrumb);
});
}
$('<li class="active">'+ doclist.current_folder_name+'</li>')


+ 3
- 2
frappe/data/Framework.sql Dosyayı Görüntüle

@@ -200,11 +200,11 @@ CREATE TABLE `__Auth` (
) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

--
-- Table structure for table `tabFile`
--

DROP TABLE IF EXISTS `tabFile Data`;
CREATE TABLE `tabFile Data` (
DROP TABLE IF EXISTS `tabFile`;
CREATE TABLE `tabFile` (
`name` varchar(255) NOT NULL,
`creation` datetime(6) DEFAULT NULL,
`modified` datetime(6) DEFAULT NULL,


+ 11
- 7
frappe/desk/search.py Dosyayı Görüntüle

@@ -59,14 +59,18 @@ def search_widget(doctype, txt, query=None, searchfield=None, start=0,

# build from doctype
if txt:
search_fields = ["name"]
if meta.title_field:
search_fields.append(meta.title_field)

if meta.search_fields:
for f in meta.get_search_fields():
fmeta = meta.get_field(f.strip())
if f == "name" or (fmeta and fmeta.fieldtype in ["Data", "Text", "Small Text", "Long Text",
"Link", "Select", "Read Only", "Text Editor"]):
or_filters.append([doctype, f.strip(), "like", "%{0}%".format(txt)])
else:
filters.append([doctype, searchfield or "name", "like", "%{0}%".format(txt)])
search_fields.extend(meta.get_search_fields())
for f in search_fields:
fmeta = meta.get_field(f.strip())
if f == "name" or (fmeta and fmeta.fieldtype in ["Data", "Text", "Small Text", "Long Text",
"Link", "Select", "Read Only", "Text Editor"]):
or_filters.append([doctype, f.strip(), "like", "%{0}%".format(txt)])

if meta.get("fields", {"fieldname":"enabled", "fieldtype":"Check"}):
filters.append([doctype, "enabled", "=", 1])


+ 4
- 0
frappe/model/document.py Dosyayı Görüntüle

@@ -86,6 +86,10 @@ class Document(BaseDocument):
self._default_new_docs = {}
self.flags = frappe._dict()

def reload(self):
"""Reload document from database"""
self.load_from_db()

def load_from_db(self):
"""Load document and children from database and create properties
from fields"""


+ 5
- 2
frappe/patches/v6_1/rename_file_data.py Dosyayı Görüntüle

@@ -7,6 +7,10 @@ def execute():
frappe.rename_doc("DocType", "File Data", "File")
frappe.reload_doctype("File")

# DELETE THIS
frappe.db.sql("""delete from tabFile where is_folder=1""")
frappe.db.sql("""update tabFile set folder=null""")

if not frappe.db.exists("File", {"is_home_folder": 1}):
make_home_folder()

@@ -14,6 +18,7 @@ def execute():
for file in frappe.get_all("File", filters={"is_folder": 0}):
file = frappe.get_doc("File", file.name)
file.flags.ignore_folder_validate = True
file.set_folder_name()
file.save()

from frappe.utils.nestedset import rebuild_tree
@@ -22,8 +27,6 @@ def execute():
# reset file size
for folder in frappe.db.sql("""select name from tabFile f1 where is_folder = 1 and
(select count(*) from tabFile f2 where f2.folder = f1.name and f2.is_folder = 1) = 0"""):
print folder[0]

folder = frappe.get_doc("File", folder[0])
folder.save()



+ 6
- 1
frappe/public/css/desk.css Dosyayı Görüntüle

@@ -523,5 +523,10 @@ ul.linked-with-list li {
}
.breadcrumb {
font-size: 12px;
margin-bottom: 10px;
background-color: #fff;
}
.breadcrumb.for-file-list {
margin-bottom: 0px;
border-bottom: 1px solid #d1d8dd;
border-radius: 0px;
}

+ 22
- 11
frappe/public/js/frappe/list/doclistview.js Dosyayı Görüntüle

@@ -14,10 +14,14 @@ frappe.views.ListFactory = frappe.views.Factory.extend({
if(locals["DocType"][doctype].issingle) {
frappe.set_re_route("Form", doctype);
} else {
new frappe.views.DocListView({
doctype: doctype,
parent: me.make_page(true)
});
if(!frappe.views.doclistview[doctype]) {
frappe.views.doclistview[doctype] = new frappe.views.DocListView({
doctype: doctype,
parent: me.make_page(true, "List/" + doctype)
});
} else {
frappe.container.change_to(frappe.views.doclistview[doctype].page_name);
}
me.set_cur_list();
}
});
@@ -65,6 +69,7 @@ frappe.views.DocListView = frappe.ui.Listing.extend({
};

this.label = __(this.doctype);
this.page_name = "List/" + this.doctype;
this.dirty = true;
this.tags_shown = false;
this.label = (this.label.toLowerCase().substr(-4) == 'list') ?
@@ -236,6 +241,7 @@ frappe.views.DocListView = frappe.ui.Listing.extend({

if(frappe.route_options) {
me.set_route_options();
me.run();
} else if(me.dirty) {
me.run();
} else {
@@ -265,17 +271,22 @@ frappe.views.DocListView = frappe.ui.Listing.extend({
}
});
frappe.route_options = null;
me.run();
},

run: function(more) {
// set filter from route
var route = frappe.get_route();
var me = this;
if(route[2]) {
$.each(frappe.utils.get_args_dict_from_url(route[2]), function(key, val) {
me.set_filter(key, val, true);
});
if(this.listview.settings.before_run) {
this.listview.settings.before_run(this);
}

if(!this.listview.settings.use_route) {
var route = frappe.get_route();
var me = this;
if(route[2]) {
$.each(frappe.utils.get_args_dict_from_url(route[2]), function(key, val) {
me.set_filter(key, val, true);
});
}
}

this.list_header.find(".list-starred-by-me")


+ 1
- 1
frappe/public/js/frappe/ui/filters/filters.js Dosyayı Görüntüle

@@ -182,7 +182,7 @@ frappe.ui.Filter = Class.extend({

if(!dont_run) {
this.flist.listobj.dirty = true;
this.flist.listobj.run();
this.flist.listobj.refresh();
}
},



+ 1
- 1
frappe/public/js/frappe/ui/toolbar/awesome_bar.js Dosyayı Görüntüle

@@ -145,7 +145,7 @@ frappe.search.verbs = [
value: __('Find {0} in {1}', [txt, route[1]]),
route_options: options,
onclick: function() {
frappe.container.page.doclistview.set_route_options();
cur_list.refresh();
},
match: txt
});


+ 10
- 6
frappe/public/js/frappe/views/factory.js Dosyayı Görüntüle

@@ -13,7 +13,9 @@ frappe.views.Factory = Class.extend({
me = this;
if(frappe.pages[page_name] && page_name.indexOf("Form/")===-1) {
frappe.container.change_to(frappe.pages[page_name]);
if(me.on_show) me.on_show();
if(me.on_show) {
me.on_show();
}
} else {
var route = frappe.get_route();
if(route[1]) {
@@ -23,14 +25,16 @@ frappe.views.Factory = Class.extend({
}
}
},
make_page: function(double_column) {
return frappe.make_page(double_column);
make_page: function(double_column, page_name) {
return frappe.make_page(double_column, page_name);
}
});

frappe.make_page = function(double_column) {
var page_name = frappe.get_route_str(),
page = frappe.container.add_page(page_name);
frappe.make_page = function(double_column, page_name) {
if(!page_name) {
var page_name = frappe.get_route_str();
}
var page = frappe.container.add_page(page_name);

frappe.ui.make_app_page({
parent: page,


+ 7
- 1
frappe/public/less/desk.less Dosyayı Görüntüle

@@ -380,5 +380,11 @@ ul.linked-with-list li {

.breadcrumb {
font-size: 12px;
margin-bottom: 10px;
background-color: #fff;
}

.breadcrumb.for-file-list {
margin-bottom: 0px;
border-bottom: 1px solid @border-color;
border-radius: 0px;
}

+ 3
- 0
frappe/utils/install.py Dosyayı Görüntüle

@@ -39,6 +39,9 @@ def after_install():
{'doctype': "Email Account", "email_id": "replies@example.com", "default_incoming": 1}
]

from frappe.core.doctype.file.file import make_home_folder
make_home_folder()

for d in install_docs:
try:
frappe.get_doc(d).insert()


Yükleniyor…
İptal
Kaydet