diff --git a/frappe/model/bean.py b/frappe/model/bean.py
index 06a31aceb9..ee21b91959 100644
--- a/frappe/model/bean.py
+++ b/frappe/model/bean.py
@@ -292,10 +292,7 @@ class Bean:
def has_permission(self, permtype):
return frappe.has_permission(self.doc.doctype, permtype, self.doc)
-
- def update_value(self, field, value):
- frappe.conn.set(self.doc, field, value)
-
+
def save(self, check_links=1, ignore_permissions=None):
if ignore_permissions:
self.ignore_permissions = ignore_permissions
diff --git a/frappe/patches/4_0/set_website_sitemap_idx.py b/frappe/patches/4_0/set_website_sitemap_idx.py
new file mode 100644
index 0000000000..315dba76ec
--- /dev/null
+++ b/frappe/patches/4_0/set_website_sitemap_idx.py
@@ -0,0 +1,14 @@
+import frappe
+
+def execute():
+ frappe.conn.sql("""update `tabWebsite Sitemap` set idx=null""")
+ # frappe.conn.sql("""update `tabWeb Page` set idx=null""")
+ # frappe.conn.sql("""update `tabBlog Post` set idx=null""")
+ # frappe.conn.sql("""update `tabBlog Category` set idx=null""")
+ # frappe.conn.sql("""update `tabWebsite Group` set idx=null""")
+ # frappe.conn.sql("""delete from `tabTable of Contents`""")
+
+ for doctype in ["Blog Category", "Blog Post", "Web Page", "Website Group"]:
+ for name in frappe.conn.get_values("Website Sitemap", {"ref_doctype":doctype}, "docname"):
+ frappe.bean(doctype, name[0]).save()
+
\ No newline at end of file
diff --git a/frappe/public/js/frappe/ui/tree.js b/frappe/public/js/frappe/ui/tree.js
index cbe51f85de..93874b9cb9 100644
--- a/frappe/public/js/frappe/ui/tree.js
+++ b/frappe/public/js/frappe/ui/tree.js
@@ -26,6 +26,7 @@ frappe.ui.Tree = Class.extend({
.tree li { list-style: none; }\
.tree ul { margin-top: 2px; }\
.tree-link { cursor: pointer; }\
+ .tree-hover { background-color: #eee; min-height: 20px; border: 1px solid #ddd; }\
")
}
})
@@ -52,7 +53,24 @@ frappe.ui.TreeNode = Class.extend({
.data('label', this.label)
.data('node', this)
.appendTo(this.parent);
-
+
+ this.$ul = $('
')
+ .css({"min-height": "5px"})
+ .toggle(false).appendTo(this.parent);
+ if(this.tree.drop && this.parent_label) {
+ this.$ul.droppable({
+ hoverClass: "tree-hover",
+ greedy: true,
+ drop: function(event, ui) {
+ event.preventDefault();
+ var dragged_node = $(ui.draggable).find(".tree-link:first").data("node");
+ var dropped_node = $(this).parent().find(".tree-link:first").data("node");
+ me.tree.drop(dragged_node, dropped_node, $(ui.draggable), $(this));
+ return false;
+ }
+ });
+ }
+
// label with icon
var icon_html = '';
if(this.expandable) {
@@ -65,6 +83,18 @@ frappe.ui.TreeNode = Class.extend({
this.tree.onrender(this);
}
},
+ addnode: function(data) {
+ var $li = $('- ');
+ if(this.tree.drop) $li.draggable({revert:true});
+ return new frappe.ui.TreeNode({
+ tree:this.tree,
+ parent: $li.appendTo(this.$ul),
+ parent_label: this.label,
+ label: data.value,
+ expandable: data.expandable,
+ data: data
+ });
+ },
selectnode: function() {
// expand children
if(this.$ul) {
@@ -94,19 +124,6 @@ frappe.ui.TreeNode = Class.extend({
}
this.load();
},
- addnode: function(data) {
- if(!this.$ul) {
- this.$ul = $('
').toggle(false).appendTo(this.parent);
- }
- return new frappe.ui.TreeNode({
- tree:this.tree,
- parent: $('- ').appendTo(this.$ul),
- parent_label: this.label,
- label: data.value,
- expandable: data.expandable,
- data: data
- });
- },
load: function() {
var me = this;
args = $.extend(this.tree.args || {}, {
diff --git a/frappe/templates/generators/blog_post.py b/frappe/templates/generators/blog_post.py
index e90994869f..975dff47da 100644
--- a/frappe/templates/generators/blog_post.py
+++ b/frappe/templates/generators/blog_post.py
@@ -9,6 +9,8 @@ from frappe.utils import global_date_format, get_fullname, cint
doctype = "Blog Post"
condition_field = "published"
+sort_by = "published_on"
+sort_order = "desc"
def get_context(context):
blog_post = context.bean.doc
diff --git a/frappe/website/doctype/blog_category/blog_category.txt b/frappe/website/doctype/blog_category/blog_category.txt
index 030bfea3fa..ed6fcad289 100644
--- a/frappe/website/doctype/blog_category/blog_category.txt
+++ b/frappe/website/doctype/blog_category/blog_category.txt
@@ -2,7 +2,7 @@
{
"creation": "2013-03-08 09:41:11",
"docstatus": 0,
- "modified": "2014-02-13 17:31:52",
+ "modified": "2014-02-18 15:25:04",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -24,6 +24,7 @@
"permlevel": 0
},
{
+ "cancel": 0,
"doctype": "DocPerm",
"email": 1,
"name": "__common__",
@@ -74,10 +75,10 @@
"label": "Page Name"
},
{
- "cancel": 0,
"create": 1,
"delete": 1,
"doctype": "DocPerm",
+ "report": 1,
"role": "Website Manager",
"write": 1
},
diff --git a/frappe/website/doctype/website_sitemap/website_sitemap.py b/frappe/website/doctype/website_sitemap/website_sitemap.py
index 33d3839012..12c194b783 100644
--- a/frappe/website/doctype/website_sitemap/website_sitemap.py
+++ b/frappe/website/doctype/website_sitemap/website_sitemap.py
@@ -4,6 +4,7 @@
from __future__ import unicode_literals
import frappe
from frappe import _
+from frappe.utils import cint
from frappe.utils.nestedset import DocTypeNestedSet
sitemap_fields = ("page_name", "ref_doctype", "docname", "page_or_generator", "idx",
@@ -29,22 +30,37 @@ class DocType(DocTypeNestedSet):
self.rename()
self.check_if_page_name_is_unique()
self.make_private_if_parent_is_private()
+ self.renumber_if_moved()
self.set_idx()
+
+ def renumber_if_moved(self):
+ if self.doc.old_parent != self.doc.parent_website_sitemap:
+ frappe.conn.sql("""update `tabWebsite Sitemap` set idx=idx-1
+ where parent_website_sitemap=%s and idx>%s""", (self.doc.old_parent, self.doc.idx))
+ frappe.conn.sql("""update `tab{}` set idx=idx-1
+ where parent_website_sitemap=%s and idx>%s""".format(self.doc.ref_doctype),
+ (self.doc.old_parent, self.doc.idx))
+ self.doc.idx = None
def set_idx(self):
if self.doc.idx==None:
- self.doc.idx = int(frappe.conn.sql("""select max(idx) from `tabWebsite Sitemap`
- where parent_website_sitemap=%s and name!=%s""", (self.doc.parent_website_sitemap,
+ self.doc.idx = int(frappe.conn.sql("""select max(ifnull(idx, -1)) from `tabWebsite Sitemap`
+ where ifnull(parent_website_sitemap, '')=%s and name!=%s""",
+ (self.doc.parent_website_sitemap or '',
self.doc.name))[0][0] or 0) + 1
else:
- if self.doc.idx != 0 and self.doc.parent_website_sitemap:
- if not frappe.conn.get_value("Website Sitemap", {
- "idx": self.doc.idx -1,
- "parent_website_sitemap":self.doc.parent_website_sitemap
- }):
+ if cint(self.doc.idx) != 0 and self.doc.parent_website_sitemap:
+ if not frappe.conn.sql("""select name from `tabWebsite Sitemap` where
+ ifnull(parent_website_sitemap, '')=%s and ifnull(idx, -1)=%s""",
+ (self.doc.parent_website_sitemap or '', cint(self.doc.idx) - 1)):
+
frappe.throw("{}: {}".format(
_("Sitemap Ordering Error. Index missing"), self.doc.idx-1))
-
+
+ def on_update(self):
+ if not frappe.flags.in_rebuild_config:
+ DocTypeNestedSet.on_update(self)
+
def rename(self):
from frappe.website.render import clear_cache
self.old_name = self.doc.name
@@ -54,14 +70,14 @@ class DocType(DocTypeNestedSet):
self.rename_links()
self.rename_descendants()
clear_cache(self.old_name)
-
+
def rename_links(self):
for doctype in frappe.conn.sql_list("""select parent from tabDocField where fieldtype='Link' and
fieldname='parent_website_sitemap' and options='Website Sitemap'"""):
for name in frappe.conn.sql_list("""select name from `tab{}`
where parent_website_sitemap=%s""".format(doctype), self.old_name):
frappe.conn.set_value(doctype, name, "parent_website_sitemap", self.doc.name)
-
+
def rename_descendants(self):
# rename children
for name in frappe.conn.sql_list("""select name from `tabWebsite Sitemap`
@@ -69,10 +85,6 @@ class DocType(DocTypeNestedSet):
child = frappe.bean("Website Sitemap", name)
child.doc.parent_website_sitemap = self.doc.name
child.save()
-
- def on_update(self):
- if not frappe.flags.in_rebuild_config:
- DocTypeNestedSet.on_update(self)
def check_if_page_name_is_unique(self):
exists = False
diff --git a/frappe/website/doctype/website_sitemap/website_sitemap.txt b/frappe/website/doctype/website_sitemap/website_sitemap.txt
index 9ee728bd1f..18bc601a14 100644
--- a/frappe/website/doctype/website_sitemap/website_sitemap.txt
+++ b/frappe/website/doctype/website_sitemap/website_sitemap.txt
@@ -2,7 +2,7 @@
{
"creation": "2013-11-18 15:38:40",
"docstatus": 0,
- "modified": "2014-02-10 18:10:11",
+ "modified": "2014-02-18 15:23:12",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -22,7 +22,9 @@
"permlevel": 0
},
{
+ "cancel": 0,
"create": 0,
+ "delete": 1,
"doctype": "DocPerm",
"name": "__common__",
"parent": "Website Sitemap",
diff --git a/frappe/website/doctype/website_sitemap_config/website_sitemap_config.py b/frappe/website/doctype/website_sitemap_config/website_sitemap_config.py
index a02549b776..12319b5737 100644
--- a/frappe/website/doctype/website_sitemap_config/website_sitemap_config.py
+++ b/frappe/website/doctype/website_sitemap_config/website_sitemap_config.py
@@ -46,6 +46,11 @@ def rebuild_website_sitemap_config():
# TODO
frappe.flags.in_rebuild_config = True
+ frappe.conn.sql("""update `tabWeb Page` set idx=null""")
+ frappe.conn.sql("""update `tabBlog Post` set idx=null""")
+ frappe.conn.sql("""update `tabBlog Category` set idx=null""")
+ frappe.conn.sql("""update `tabWebsite Group` set idx=null""")
+
frappe.conn.sql("""delete from `tabWebsite Sitemap Config`""")
for app in frappe.get_installed_apps():
if app=="webnotes": app="frappe"
@@ -64,15 +69,25 @@ def build_website_sitemap_config(app):
config = {"pages": {}, "generators":{}}
basepath = frappe.get_pymodule_path(app)
- # pages
+ pages = []
+ generators = []
+
for config_type in ("pages", "generators"):
path = os.path.join(basepath, "templates", config_type)
if os.path.exists(path):
for fname in os.listdir(path):
fname = frappe.utils.cstr(fname)
if fname.split(".")[-1] in ("html", "xml", "js", "css"):
- name = add_website_sitemap_config("Page" if config_type=="pages" else "Generator",
- app, path, fname, basepath)
+ if config_type=="pages":
+ pages.append(["Page", app, path, fname, basepath])
+ else:
+ generators(["Generator", app, path, fname, basepath])
+
+ for args in pages:
+ add_website_sitemap_config(*args)
+
+ for args in generators:
+ add_website_sitemap_config(*args)
frappe.conn.commit()
@@ -100,6 +115,8 @@ def add_website_sitemap_config(page_or_generator, app, path, fname, basepath):
wsc.ref_doctype = getattr(module, "doctype", None)
wsc.page_name_field = getattr(module, "page_name_field", "page_name")
wsc.condition_field = getattr(module, "condition_field", None)
+ wsc.sort_by = getattr(module, "sort_by", "name")
+ wsc.sort_order = getattr(module, "sort_order", "asc")
wsc.base_template_path = getattr(module, "base_template_path", None)
wsc.page_title = getattr(module, "page_title", _(name.title()))
diff --git a/frappe/website/doctype/website_sitemap_config/website_sitemap_config.txt b/frappe/website/doctype/website_sitemap_config/website_sitemap_config.txt
index 74e913755c..c5b784c339 100644
--- a/frappe/website/doctype/website_sitemap_config/website_sitemap_config.txt
+++ b/frappe/website/doctype/website_sitemap_config/website_sitemap_config.txt
@@ -2,7 +2,7 @@
{
"creation": "2013-11-18 15:35:00",
"docstatus": 0,
- "modified": "2014-02-14 12:48:54",
+ "modified": "2014-02-18 15:22:32",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -22,7 +22,9 @@
"permlevel": 0
},
{
+ "cancel": 0,
"create": 0,
+ "delete": 1,
"doctype": "DocPerm",
"export": 0,
"name": "__common__",
@@ -129,6 +131,18 @@
"label": "Condition Field",
"read_only": 1
},
+ {
+ "doctype": "DocField",
+ "fieldname": "sort_by",
+ "fieldtype": "Data",
+ "label": "Sort By"
+ },
+ {
+ "doctype": "DocField",
+ "fieldname": "sort_order",
+ "fieldtype": "Data",
+ "label": "Sort Order"
+ },
{
"doctype": "DocPerm"
}
diff --git a/frappe/website/page/sitemap_browser/sitemap_browser.js b/frappe/website/page/sitemap_browser/sitemap_browser.js
index 1be0611feb..c948ccc16e 100644
--- a/frappe/website/page/sitemap_browser/sitemap_browser.js
+++ b/frappe/website/page/sitemap_browser/sitemap_browser.js
@@ -25,7 +25,6 @@ frappe.pages['sitemap-browser'].onload = function(wrapper) {
"min-height": "300px",
"padding-bottom": "25px"
}));
-
}
frappe.provide("frappe.website");
@@ -49,7 +48,15 @@ frappe.website.SitemapBrowser = Class.extend({
me.cur_toolbar = link.toolbar;
$(me.cur_toolbar).toggle(true);
}
- }
+ },
+ // drop: function(dragged_node, dropped_node, dragged_element, dropped_element) {
+ // frappe.website.sitemap.update_parent(dragged_node.label, dropped_node.label, function(r) {
+ // if(!r.exc) {
+ // dragged_element.remove();
+ // dropped_node.reload();
+ // }
+ // });
+ // }
});
this.tree.rootnode.$a
.data('node-data', {value: "Sitemap", expandable:1})
@@ -65,65 +72,12 @@ frappe.website.SitemapBrowser = Class.extend({
var node_links = [];
node_links.push(''+frappe._('Edit')+'');
- node_links.push(''+frappe._('Move')+'');
+ node_links.push(''+frappe._('Move')+'');
node_links.push(''+frappe._('Up')+'');
node_links.push(''+frappe._('Down')+'');
-
- // if(data.expandable) {
- // node_links.push('' + frappe._('Add Child') + '');
- // }
- //
- // node_links.push('' + frappe._('Delete') + '');
link.toolbar.append(node_links.join(" | "));
},
- new_node: function() {
- var me = this;
-
- var fields = [
- {fieldtype:'Data', fieldname: 'name_field',
- label:'New ' + me.ctype + ' Name', reqd:true},
- {fieldtype:'Select', fieldname:'is_group', label:'Group Node', options:'No\nYes',
- description: frappe._("Further nodes can be only created under 'Group' type nodes")},
- {fieldtype:'Button', fieldname:'create_new', label:'Create New' }
- ]
-
- if(me.ctype == "Sales Person") {
- fields.splice(-1, 0, {fieldtype:'Link', fieldname:'employee', label:'Employee',
- options:'Employee', description: frappe._("Please enter Employee Id of this sales parson")});
- }
-
- // the dialog
- var d = new frappe.ui.Dialog({
- title: frappe._('New ') + frappe._(me.ctype),
- fields: fields
- })
-
- d.set_value("is_group", "No");
- // create
- $(d.fields_dict.create_new.input).click(function() {
- var btn = this;
- $(btn).set_working();
- var v = d.get_values();
- if(!v) return;
-
- var node = me.selected_node();
-
- v.parent = node.data('label');
- v.ctype = me.ctype;
-
- return frappe.call({
- method: 'erpnext.selling.page.sales_browser.sales_browser.add_node',
- args: v,
- callback: function() {
- $(btn).done_working();
- d.hide();
- node.trigger('reload');
- }
- })
- });
- d.show();
- },
selected_node: function() {
return this.tree.$w.find('.tree-link.selected');
},
@@ -140,13 +94,16 @@ frappe.website.SitemapBrowser = Class.extend({
"up_or_down": up_or_down
},
callback: function(r) {
- (node.parent_node || node).reload();
+ if(r.message==="ok") {
+ node.parent.insertBefore(up_or_down==="up" ?
+ node.parent.prev() : node.parent.next().next());
+ //(node.parent_node || node).reload();
+ }
}
});
},
- move: function() {
+ update_parent: function() {
var me = this;
- var node = this.selected_node();
if(!this.move_dialog) {
this.move_dialog = new frappe.ui.Dialog({
title: frappe._("Move"),
@@ -166,23 +123,29 @@ frappe.website.SitemapBrowser = Class.extend({
]
});
this.move_dialog.get_input("update").on("click", function() {
+ var node = me.tree.get_selected_node();
var values = me.move_dialog.get_values();
if(!values) return;
- frappe.call({
- method: "frappe.website.page.sitemap_browser.sitemap_browser.update_parent",
- args: {
- "name": node.data("label"),
- "new_parent": values.new_parent
- },
- callback: function(r) {
- me.move_dialog.hide();
- me.tree.rootnode.reload();
- }
- });
+ me.update_parent(node.label, values.new_parent, function(r) {
+ me.move_dialog.hide();
+ (node.parent_node || node).reload();
+ })
});
}
this.move_dialog.show();
this.move_dialog.get_input("new_parent").val("");
+ },
+ update_parent: function(name, parent, callback) {
+ frappe.call({
+ method: "frappe.website.page.sitemap_browser.sitemap_browser.update_parent",
+ args: {
+ "name": name,
+ "new_parent": parent
+ },
+ callback: function(r) {
+ callback(r);
+ }
+ });
}
});
\ No newline at end of file
diff --git a/frappe/website/page/sitemap_browser/sitemap_browser.py b/frappe/website/page/sitemap_browser/sitemap_browser.py
index be90de2622..5de66247bc 100644
--- a/frappe/website/page/sitemap_browser/sitemap_browser.py
+++ b/frappe/website/page/sitemap_browser/sitemap_browser.py
@@ -14,7 +14,7 @@ def get_children(parent=None):
parent = ""
return frappe.conn.sql("""select name as value, 1 as expandable from `tabWebsite Sitemap` where
- ifnull(parent_website_sitemap, '')=%s order by -idx desc""", parent, as_dict=True)
+ ifnull(parent_website_sitemap, '')=%s and idx is not null order by -idx desc""", parent, as_dict=True)
@frappe.whitelist()
def move(name, up_or_down):
@@ -51,6 +51,7 @@ def move(name, up_or_down):
ret = "ok"
clear_cache()
+ return ret
@frappe.whitelist()
def update_parent(name, new_parent):