From ffe082d7a98219a9d96aa2b5286a5c4545aab1c8 Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Thu, 30 Jan 2014 20:50:31 +0530 Subject: [PATCH] Response to a Website Page Request would be json content if ajax else full page html Related to (#421): Fixed base template Blog, Blog Post, Login, App pages Started with porting Unit Template to Website Group Template --- webnotes/__init__.py | 5 +- webnotes/handler.py | 2 +- webnotes/hooks.txt | 9 +- webnotes/templates/base.html | 68 +++--- webnotes/templates/generators/blog_post.html | 2 - webnotes/templates/generators/blog_post.py | 71 +++++- .../templates/generators/website_group.html | 11 + .../templates/generators/website_group.py | 104 ++++++++ webnotes/templates/includes/blog.css | 7 - webnotes/templates/includes/blog.js | 3 +- webnotes/templates/includes/navbar.html | 47 ++-- webnotes/templates/pages/app.html | 2 +- webnotes/templates/pages/app.py | 4 +- webnotes/templates/pages/blog.html | 19 +- webnotes/templates/pages/blog.py | 11 +- webnotes/templates/pages/login.html | 23 +- webnotes/templates/pages/login.py | 5 +- webnotes/templates/website_group/__init__.py | 0 .../templates/website_group/edit_post.html | 0 webnotes/templates/website_group/events.html | 0 webnotes/templates/website_group/forum.html | 0 webnotes/templates/website_group/post.html | 0 .../templates/website_group/settings.html | 0 webnotes/templates/website_group/tasks.html | 0 webnotes/utils/__init__.py | 5 + webnotes/website/css/website.css | 6 + .../website/doctype/blog_post/blog_post.py | 72 +----- .../doctype/website_group/website_group.py | 4 + .../website_sitemap/website_sitemap.txt | 9 +- .../website_sitemap_config.py | 1 + .../website_sitemap_config.txt | 9 +- .../website_sitemap_permission.py | 57 ++++- webnotes/webutils.py | 222 ++++++++++++------ 33 files changed, 528 insertions(+), 250 deletions(-) delete mode 100644 webnotes/templates/includes/blog.css create mode 100644 webnotes/templates/website_group/__init__.py create mode 100644 webnotes/templates/website_group/edit_post.html create mode 100644 webnotes/templates/website_group/events.html create mode 100644 webnotes/templates/website_group/forum.html create mode 100644 webnotes/templates/website_group/post.html create mode 100644 webnotes/templates/website_group/settings.html create mode 100644 webnotes/templates/website_group/tasks.html diff --git a/webnotes/__init__.py b/webnotes/__init__.py index 05847949f3..b24829b536 100644 --- a/webnotes/__init__.py +++ b/webnotes/__init__.py @@ -199,7 +199,7 @@ def throw(msg, exc=ValidationError): def create_folder(path): if not os.path.exists(path): os.makedirs(path) - + def connect(site=None, db_name=None): from db import Database if site: @@ -546,13 +546,14 @@ def get_jenv(): return jenv def set_filters(jenv): - from webnotes.utils import global_date_format + from webnotes.utils import global_date_format, scrub_relative_url from markdown2 import markdown from json import dumps jenv.filters["global_date_format"] = global_date_format jenv.filters["markdown"] = markdown jenv.filters["json"] = dumps + jenv.filters["scrub_relative_url"] = scrub_relative_url # load jenv_filters from hooks.txt for app in get_all_apps(True): diff --git a/webnotes/handler.py b/webnotes/handler.py index 95d28e6631..32e3de074f 100755 --- a/webnotes/handler.py +++ b/webnotes/handler.py @@ -171,7 +171,7 @@ def print_json(): make_logs() cleanup_docs() - webnotes._response.headers["Content-Type"] = "text/json; charset: utf-8" + webnotes._response.headers["Content-Type"] = "application/json; charset: utf-8" import json diff --git a/webnotes/hooks.txt b/webnotes/hooks.txt index de96d2d02e..6d9d5c5b81 100644 --- a/webnotes/hooks.txt +++ b/webnotes/hooks.txt @@ -8,11 +8,16 @@ app_color = #3498db after_install = webnotes.utils.install.after_install +# website app_include_js = assets/js/webnotes.min.js app_include_css = assets/webnotes/css/splash.css app_include_css = assets/css/webnotes.css web_include_js = assets/js/webnotes-web.min.js web_include_css = assets/css/webnotes-web.css +website_group_views:Forum = webnotes.templates.website_group.forum.get_views +website_group_views:Events = webnotes.templates.website_group.events.get_views +website_group_views:Tasks = webnotes.templates.website_group.tasks.get_views + get_desktop_icons = webnotes.manage.get_desktop_icons notification_config = webnotes.core.notifications.get_notification_config @@ -26,7 +31,7 @@ on_session_creation = webnotes.auth.notify_administrator_login # permissions permission_query_conditions:Event = webnotes.core.doctype.event.event.get_permission_query_conditions -has_permission:Event = webnotes.core.doctype.event.event.has_permission +has_permission:Event = webnotes.core.doctype.event.event.has_permission permission_query_conditions:ToDo = webnotes.core.doctype.todo.todo.get_permission_query_conditions -has_permission:ToDo = webnotes.core.doctype.todo.todo.has_permission \ No newline at end of file +has_permission:ToDo = webnotes.core.doctype.todo.todo.has_permission \ No newline at end of file diff --git a/webnotes/templates/base.html b/webnotes/templates/base.html index b6b614324f..8f99736519 100644 --- a/webnotes/templates/base.html +++ b/webnotes/templates/base.html @@ -6,37 +6,51 @@ {{ title }} - - - {% block head %} - {% if meta_description -%} - {%- endif %} - {% for link in web_include_js -%} + + + + + {%- block head -%} + {%- if meta_description -%} + + {%- endif -%} + + {%- for link in web_include_js -%} - {%- endfor %} - {% for link in web_include_css -%} + {%- endfor -%} + + {%- for link in web_include_css -%} - {%- endfor %} - {% endblock %} - {% block javascript -%} - {% if javascript %}{% endif %} - {%- endblock %} - {% block css -%} - {% if css %}{% endif %} - {%- endblock %} - {% block style -%}{%- endblock %} + {%- endfor -%} + {%- endblock -%} + + {%- block javascript -%} + {%- if javascript -%} + + {%- endif -%} + {%- endblock -%} + + {%- block css -%} + {%- if css -%} + + {%- endif -%} + {%- endblock -%} + + {%- block style -%}{%- endblock -%} - {% block banner %} - {% if banner_html -%} -
{{ banner_html or "" }}
- {%- endif %} - {% endblock %} - {% block navbar %}{% include "templates/includes/navbar.html" %}{% endblock %} -
- {% block content %}{% endblock %} + {%- block banner -%} + {% if banner_html -%} +
{{ banner_html or "" }}
+ {%- endif %} + {%- endblock -%} + + {%- block navbar -%}{% include "templates/includes/navbar.html" %}{%- endblock -%} + +
+ {%- block content -%}{{ content }}{%- endblock -%}
- {% block footer %}{% include "templates/includes/footer.html" %}{% endblock %} - {% block script -%}{%- endblock %} + + {%- block footer -%}{% include "templates/includes/footer.html" %}{%- endblock -%} \ No newline at end of file diff --git a/webnotes/templates/generators/blog_post.html b/webnotes/templates/generators/blog_post.html index 1ddf7d5ac5..6313920325 100644 --- a/webnotes/templates/generators/blog_post.html +++ b/webnotes/templates/generators/blog_post.html @@ -1,5 +1,3 @@ -{% extends base_template %} - {% block content %}

{{ title }}

diff --git a/webnotes/templates/generators/blog_post.py b/webnotes/templates/generators/blog_post.py index fde975401e..270add370c 100644 --- a/webnotes/templates/generators/blog_post.py +++ b/webnotes/templates/generators/blog_post.py @@ -1,2 +1,71 @@ +# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors +# MIT License. See license.txt + +from __future__ import unicode_literals + +import markdown2 +import webnotes +from webnotes.utils import global_date_format, get_fullname, cint + doctype = "Blog Post" -condition_field = "published" \ No newline at end of file +condition_field = "published" + +def get_context(context): + blog_post = webnotes.doc(context.ref_doctype, context.docname) + + # this is for double precaution. usually it wont reach this code if not published + if not cint(blog_post.published): + raise Exception, "This blog has not been published yet!" + + # temp fields + blog_post.full_name = get_fullname(blog_post.owner) + blog_post.updated = global_date_format(blog_post.published_on) + + if blog_post.blogger: + blog_post.blogger_info = webnotes.doc("Blogger", blog_post.blogger).fields + + blog_post.description = blog_post.blog_intro or blog_post.content[:140] + blog_post.meta_description = blog_post.description + + blog_post.categories = webnotes.conn.sql_list("select name from `tabBlog Category` order by name") + + blog_post.comment_list = webnotes.conn.sql("""\ + select comment, comment_by_fullname, creation + from `tabComment` where comment_doctype="Blog Post" + and comment_docname=%s order by creation""", (blog_post.name,), as_dict=1) or [] + + blog_post.fields.update(context) + + return { "title": blog_post.title, "content": context.template.render(blog_post.fields) } + +@webnotes.whitelist(allow_guest=True) +def get_blog_list(start=0, by=None, category=None): + condition = "" + if by: + condition = " and t1.blogger='%s'" % by.replace("'", "\'") + if category: + condition += " and t1.blog_category='%s'" % category.replace("'", "\'") + query = """\ + select + t1.title, t1.name, t1.page_name, t1.published_on as creation, + ifnull(t1.blog_intro, t1.content) as content, + t2.full_name, t2.avatar, t1.blogger, + (select count(name) from `tabComment` where + comment_doctype='Blog Post' and comment_docname=t1.name) as comments + from `tabBlog Post` t1, `tabBlogger` t2 + where ifnull(t1.published,0)=1 + and t1.blogger = t2.name + %(condition)s + order by published_on desc, name asc + limit %(start)s, 20""" % {"start": start, "condition": condition} + + result = webnotes.conn.sql(query, as_dict=1) + + # strip html tags from content + for res in result: + res['published'] = global_date_format(res['creation']) + if not res['content']: + res['content'] = webnotes.webutils.get_html(res['page_name']) + res['content'] = res['content'][:140] + + return result diff --git a/webnotes/templates/generators/website_group.html b/webnotes/templates/generators/website_group.html index 46e3c764ec..9637f706bf 100644 --- a/webnotes/templates/generators/website_group.html +++ b/webnotes/templates/generators/website_group.html @@ -1,4 +1,15 @@ {% extends base_template %} {% block content %} +{{ content }} + +{%- if access -%} + +{%- endif -%} + {% endblock %} diff --git a/webnotes/templates/generators/website_group.py b/webnotes/templates/generators/website_group.py index 33d0fa0d20..960b4b953c 100644 --- a/webnotes/templates/generators/website_group.py +++ b/webnotes/templates/generators/website_group.py @@ -1 +1,105 @@ +# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors +# MIT License. See license.txt + +import webnotes +from webnotes.webutils import get_access + doctype = "Website Group" +no_cache = 1 + +def get_context(controller, page_options): + group, view = guess_group_view(controller, page_options) + + try: + if not has_access(group, view): + raise webnotes.PermissionError + + context = get_initial_context(group, view, controller) + context["access"] = get_access(group) + context["content"] = get_content(context) + + return context + + except webnotes.DoesNotExistError: + return { + "content": '
' + 'The page you are looking for does not exist.
' + } + except webnotes.PermissionError: + return { + "content": '
' + 'You are not permitted to view this page.
' + } + +def get_initial_context(group, view, controller): + def _get_initial_context(): + if controller: + group = controller.doc + else: + group = webnotes.doc("Website Group", group) + + # move all this to webutils + + + parents = webnotes.conn.sql("""select name, unit_title from tabUnit + where lft < %s and rgt > %s order by lft asc""", (unit.lft, unit.rgt), as_dict=1) + + # update title + title = unit.unit_title + views = get_views(unit) + view_options = views.get(view, {}) + if view_options: + title += " - " + view_options["label"] + + views = sorted([opts for v, opts in views.items()], key=lambda d: d.get("idx")) + context = { + "name": unit.name, + "public_read": unit.public_read, + "title": "Aam Aadmi Party: " + title, + "unit_title": title, + "public_write": unit.public_write, + "parents": parents, + "children": get_child_unit_items(unit.name, public_read=1), + "unit": unit.fields, + "view": view, + "views": views, + "view_options": view_options + } + return context + + if webnotes.conf.get("disable_website_cache"): + return _get_unit_context(unit, view) + + return webnotes.cache().get_value("unit_context:{unit}:{view}".format(unit=unit.lower(), view=view), + lambda:_get_unit_context(unit, view)) + +def get_content(context): + pass + +def guess_group_view(controller, page_options): + group = page_options.docname + + view = None + pathname = webnotes.request.path[1:] + if "/" in pathname: + view = pathname.split("/", 1)[1] + + if not view: + get_views = webnotes.get_hooks("website_group_views:{}".controller.doc.group_type) + if get_views: + for v, opts in webnotes.get_attr(get_views)(group).items(): + if opts.get("default"): + view = v + break + + return group, view + +def has_access(group, view): + access = get_access(group) + + if view=="settings": + return access.get("admin") + elif view in ("add", "edit"): + return access.get("write") + else: + return access.get("read") \ No newline at end of file diff --git a/webnotes/templates/includes/blog.css b/webnotes/templates/includes/blog.css deleted file mode 100644 index 199df1ac77..0000000000 --- a/webnotes/templates/includes/blog.css +++ /dev/null @@ -1,7 +0,0 @@ - \ No newline at end of file diff --git a/webnotes/templates/includes/blog.js b/webnotes/templates/includes/blog.js index edde41566e..8cff823eed 100644 --- a/webnotes/templates/includes/blog.js +++ b/webnotes/templates/includes/blog.js @@ -28,7 +28,7 @@ var blog = { method: "GET", url: "/", data: { - cmd: "webnotes.website.doctype.blog_post.blog_post.get_blog_list", + cmd: "webnotes.templates.generators.blog_post.get_blog_list", start: blog.start, by: get_url_arg("by"), category: get_url_arg("category") @@ -55,6 +55,7 @@ var blog = { } b.page_name = encodeURIComponent(b.page_name); + b.avatar = b.avatar || ""; $(repl('
\
\ diff --git a/webnotes/templates/includes/navbar.html b/webnotes/templates/includes/navbar.html index dc8d67687e..55a57ddef8 100644 --- a/webnotes/templates/includes/navbar.html +++ b/webnotes/templates/includes/navbar.html @@ -1,15 +1,17 @@
- diff --git a/webnotes/templates/pages/app.html b/webnotes/templates/pages/app.html index 4bfe665c56..8b2465b9d9 100644 --- a/webnotes/templates/pages/app.html +++ b/webnotes/templates/pages/app.html @@ -16,7 +16,7 @@ {% for include in include_css -%} {%- endfor -%} - + -{% endblock %} - -{% block css %} - -{% endblock %} - -{% set title="Blog" %} - {% block content %}

{{ blog_title }}

@@ -34,4 +18,7 @@
{% include 'templates/includes/blog_footer.html' %} + {% endblock %} \ No newline at end of file diff --git a/webnotes/templates/pages/blog.py b/webnotes/templates/pages/blog.py index fde575cefa..5103896250 100644 --- a/webnotes/templates/pages/blog.py +++ b/webnotes/templates/pages/blog.py @@ -3,6 +3,13 @@ from __future__ import unicode_literals import webnotes +from webnotes import _ -def get_context(): - return webnotes.doc("Blog Settings", "Blog Settings").fields \ No newline at end of file +def get_context(context): + extended_context = webnotes.doc("Blog Settings", "Blog Settings").fields + extended_context.update(context) + + return { + "title": extended_context.blog_title or "Blog", + "content": context.template.render(extended_context) + } \ No newline at end of file diff --git a/webnotes/templates/pages/login.html b/webnotes/templates/pages/login.html index 65423827a7..53e3cbadfd 100644 --- a/webnotes/templates/pages/login.html +++ b/webnotes/templates/pages/login.html @@ -1,23 +1,4 @@ -{% extends base_template %} - -{% block css %} - -{% endblock %} - -{% set title=_("Login") %} - {% block content %} - -{% if not top_bar_items %} - -{% endif %} -
@@ -44,7 +25,7 @@
-
@@ -60,6 +41,4 @@ - - {% endblock %} \ No newline at end of file diff --git a/webnotes/templates/pages/login.py b/webnotes/templates/pages/login.py index 25f54d8658..0d9887fa67 100644 --- a/webnotes/templates/pages/login.py +++ b/webnotes/templates/pages/login.py @@ -1,6 +1,7 @@ import webnotes -def get_context(): +def get_context(context): return { - "title": webnotes._("Login") + "title": webnotes._("Login"), + "content": context.template.render(context) } \ No newline at end of file diff --git a/webnotes/templates/website_group/__init__.py b/webnotes/templates/website_group/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/webnotes/templates/website_group/edit_post.html b/webnotes/templates/website_group/edit_post.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/webnotes/templates/website_group/events.html b/webnotes/templates/website_group/events.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/webnotes/templates/website_group/forum.html b/webnotes/templates/website_group/forum.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/webnotes/templates/website_group/post.html b/webnotes/templates/website_group/post.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/webnotes/templates/website_group/settings.html b/webnotes/templates/website_group/settings.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/webnotes/templates/website_group/tasks.html b/webnotes/templates/website_group/tasks.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/webnotes/utils/__init__.py b/webnotes/utils/__init__.py index 1614f0c66c..ac5e7d7987 100644 --- a/webnotes/utils/__init__.py +++ b/webnotes/utils/__init__.py @@ -841,6 +841,11 @@ def get_url_to_form(doctype, name, base_url=None, label=None): if not label: label = name return """%(label)s""" % locals() + +def scrub_relative_url(url): + if not url or url.startswith("http"): + return url + return "/" + url def encode_dict(d, encoding="utf-8"): for key in d: diff --git a/webnotes/website/css/website.css b/webnotes/website/css/website.css index 41992070b7..3401da2047 100644 --- a/webnotes/website/css/website.css +++ b/webnotes/website/css/website.css @@ -1,3 +1,9 @@ +@media (min-width: 992px) { + .login-wrapper { + border-right: 1px solid #f2f2f2; + } +} + h1, h2, h3, h4, h5 { font-weight: bold; } diff --git a/webnotes/website/doctype/blog_post/blog_post.py b/webnotes/website/doctype/blog_post/blog_post.py index 2926790097..b54754473b 100644 --- a/webnotes/website/doctype/blog_post/blog_post.py +++ b/webnotes/website/doctype/blog_post/blog_post.py @@ -4,8 +4,7 @@ from __future__ import unicode_literals import webnotes -import webnotes.webutils -from webnotes.webutils import WebsiteGenerator, cleanup_page_name +from webnotes.webutils import WebsiteGenerator, cleanup_page_name, delete_page_cache from webnotes import _ from webnotes.utils import today @@ -30,74 +29,11 @@ class DocType(WebsiteGenerator): def on_update(self): WebsiteGenerator.on_update(self) - webnotes.webutils.delete_page_cache("writers") + delete_page_cache("writers") - def get_context(self): - import webnotes.utils - import markdown2 - - # this is for double precaution. usually it wont reach this code if not published - if not webnotes.utils.cint(self.doc.published): - raise Exception, "This blog has not been published yet!" - - # temp fields - from webnotes.utils import global_date_format, get_fullname - self.doc.full_name = get_fullname(self.doc.owner) - self.doc.updated = global_date_format(self.doc.published_on) - - if self.doc.blogger: - self.doc.blogger_info = webnotes.doc("Blogger", self.doc.blogger).fields - - self.doc.description = self.doc.blog_intro or self.doc.content[:140] - self.doc.meta_description = self.doc.description - - self.doc.categories = webnotes.conn.sql_list("select name from `tabBlog Category` order by name") - - self.doc.comment_list = webnotes.conn.sql("""\ - select comment, comment_by_fullname, creation - from `tabComment` where comment_doctype="Blog Post" - and comment_docname=%s order by creation""", (self.doc.name,), as_dict=1) or [] - - def clear_blog_cache(): for blog in webnotes.conn.sql_list("""select page_name from `tabBlog Post` where ifnull(published,0)=1"""): - webnotes.webutils.delete_page_cache(blog) - - webnotes.webutils.delete_page_cache("writers") - -@webnotes.whitelist(allow_guest=True) -def get_blog_list(start=0, by=None, category=None): - import webnotes - condition = "" - if by: - condition = " and t1.blogger='%s'" % by.replace("'", "\'") - if category: - condition += " and t1.blog_category='%s'" % category.replace("'", "\'") - query = """\ - select - t1.title, t1.name, t1.page_name, t1.published_on as creation, - ifnull(t1.blog_intro, t1.content) as content, - t2.full_name, t2.avatar, t1.blogger, - (select count(name) from `tabComment` where - comment_doctype='Blog Post' and comment_docname=t1.name) as comments - from `tabBlog Post` t1, `tabBlogger` t2 - where ifnull(t1.published,0)=1 - and t1.blogger = t2.name - %(condition)s - order by published_on desc, name asc - limit %(start)s, 20""" % {"start": start, "condition": condition} - - result = webnotes.conn.sql(query, as_dict=1) - - # strip html tags from content - import webnotes.utils + delete_page_cache(blog) - for res in result: - from webnotes.utils import global_date_format - res['published'] = global_date_format(res['creation']) - if not res['content']: - res['content'] = webnotes.webutils.get_html(res['page_name']) - res['content'] = res['content'][:140] - - return result + delete_page_cache("writers") diff --git a/webnotes/website/doctype/website_group/website_group.py b/webnotes/website/doctype/website_group/website_group.py index 7f950307b2..6ff25964d6 100644 --- a/webnotes/website/doctype/website_group/website_group.py +++ b/webnotes/website/doctype/website_group/website_group.py @@ -4,6 +4,7 @@ from __future__ import unicode_literals import webnotes from webnotes.webutils import WebsiteGenerator, cleanup_page_name +from webnotes.templates.generators.website_group import get_context class DocType(WebsiteGenerator): def __init__(self, d, dl): @@ -26,3 +27,6 @@ class DocType(WebsiteGenerator): if not self.doc.page_name: webnotes.throw(_("Page Name is mandatory"), raise_exception=webnotes.MandatoryError) + + def get_context(self, page_options): + return get_context(self, page_options) diff --git a/webnotes/website/doctype/website_sitemap/website_sitemap.txt b/webnotes/website/doctype/website_sitemap/website_sitemap.txt index 8f012aaffb..5b4ce0d191 100644 --- a/webnotes/website/doctype/website_sitemap/website_sitemap.txt +++ b/webnotes/website/doctype/website_sitemap/website_sitemap.txt @@ -2,7 +2,7 @@ { "creation": "2013-11-18 15:38:40", "docstatus": 0, - "modified": "2014-01-30 11:37:09", + "modified": "2014-01-30 16:50:49", "modified_by": "Administrator", "owner": "Administrator" }, @@ -54,6 +54,13 @@ "read_only": 1, "reqd": 1 }, + { + "doctype": "DocField", + "fieldname": "page_title", + "fieldtype": "Data", + "label": "Page Title", + "read_only": 1 + }, { "doctype": "DocField", "fieldname": "ref_doctype", diff --git a/webnotes/website/doctype/website_sitemap_config/website_sitemap_config.py b/webnotes/website/doctype/website_sitemap_config/website_sitemap_config.py index a54b32d608..4ec692af3f 100644 --- a/webnotes/website/doctype/website_sitemap_config/website_sitemap_config.py +++ b/webnotes/website/doctype/website_sitemap_config/website_sitemap_config.py @@ -90,6 +90,7 @@ 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.base_template_path = getattr(module, "base_template_path", None) if webnotes.conn.exists("Website Sitemap Config", wsc.link_name): # found by earlier app, override diff --git a/webnotes/website/doctype/website_sitemap_config/website_sitemap_config.txt b/webnotes/website/doctype/website_sitemap_config/website_sitemap_config.txt index b8a4aea4cc..85bc816de5 100644 --- a/webnotes/website/doctype/website_sitemap_config/website_sitemap_config.txt +++ b/webnotes/website/doctype/website_sitemap_config/website_sitemap_config.txt @@ -2,7 +2,7 @@ { "creation": "2013-11-18 15:35:00", "docstatus": 0, - "modified": "2014-01-29 18:05:09", + "modified": "2014-01-30 17:25:27", "modified_by": "Administrator", "owner": "Administrator" }, @@ -62,6 +62,13 @@ "label": "Link Name", "read_only": 1 }, + { + "doctype": "DocField", + "fieldname": "base_template_path", + "fieldtype": "Data", + "label": "Base Template Path", + "read_only": 1 + }, { "doctype": "DocField", "fieldname": "template_path", diff --git a/webnotes/website/doctype/website_sitemap_permission/website_sitemap_permission.py b/webnotes/website/doctype/website_sitemap_permission/website_sitemap_permission.py index 50331d2eb0..6982d9478e 100644 --- a/webnotes/website/doctype/website_sitemap_permission/website_sitemap_permission.py +++ b/webnotes/website/doctype/website_sitemap_permission/website_sitemap_permission.py @@ -19,5 +19,58 @@ def remove_empty_permissions(): webnotes.conn.sql("""delete from `tabWebsite Sitemap Permission` where ifnull(`read`, 0)=0 and ifnull(`write`, 0)=0 and ifnull(`admin`, 0)=0""") - # TODO clear permissions cache for permissions_cache_to_be_cleared - \ No newline at end of file + clear_permissions(permissions_cache_to_be_cleared) + +def get_access(website_node, profile=None): + profile = profile or webnotes.session.user + key = "website_sitemap_permissions:{}".format(profile) + + cache = webnotes.cache() + permissions = cache.get_value(key) or {} + if not permissions.get(website_node): + permissions[website_node] = _get_access(website_node, profile) + cache.set_value(key, permissions) + + return permissions.get(website_node) + +def _get_access(website_node, profile): + lft, rgt, public_read, public_write = webnotes.conn.get_value("Website Sitemap", website_node, + ["lft", "rgt", "public_read", "public_write"]) + + if not (lft and rgt): + raise webnotes.ValidationError("Please rebuild Website Sitemap Tree") + + if profile == "Guest": + return { "read": public_read, "write": 0, "admin": 0 } + + read = write = admin = private_read = 0 + + if public_write: + read = write = 1 + elif public_read: + read = 1 + + for perm in webnotes.conn.sql("""select wsp.`read`, wsp.`write`, wsp.`admin`, + ws.lft, ws.rgt, ws.name + from `tabWebsite Sitemap Permission` up, `tabWebsite Sitemap` ws + where wsp.profile = %s and wsp.website_sitemap = ws.name + order by lft asc""", (profile,), as_dict=True): + if perm.lft <= lft and perm.rgt >= rgt: + if not (public_read or private_read): private_read = perm.read + if not read: read = perm.read + if not write: write = perm.write + if not admin: admin = perm.admin + if write: read = write + + if read and write and admin: + break + + return { "read": read, "write": write, "admin": admin, "private_read": private_read } + +def clear_permissions(profiles): + if isinstance(profiles, basestring): + profiles = [profiles] + + cache = webnotes.cache() + for profile in profiles: + cache.delete_value("website_sitemap_permissions:{}".format(profile)) diff --git a/webnotes/webutils.py b/webnotes/webutils.py index c1bbce8831..0f6c97cbd3 100644 --- a/webnotes/webutils.py +++ b/webnotes/webutils.py @@ -2,124 +2,156 @@ # MIT License. See license.txt from __future__ import unicode_literals -from webnotes import conf import webnotes import json, os, time from webnotes import _ import webnotes.utils +from webnotes.utils import get_request_site_address, encode, cint +from webnotes.model import default_fields from webnotes.model.controller import DocListController +from urllib import quote + import mimetypes from webnotes.website.doctype.website_sitemap.website_sitemap import add_to_sitemap, update_sitemap, remove_sitemap +# for access as webnotes.webutils.fn +from webnotes.website.doctype.website_sitemap_permission.website_sitemap_permission \ + import get_access + class PageNotFoundError(Exception): pass def render(page_name): """render html page""" - if not page_name: - page_name = "index" + page_name = scrub_page_name(page_name) - if "/" in page_name: - page_name = page_name.split("/")[0] - try: - html = render_page(page_name) + data = render_page(page_name) except Exception: - html = render_page("error") + page_name = "error" + data = render_page(page_name) + data = insert_traceback(data) - webnotes._response.data = html + data = set_content_type(data, page_name) + webnotes._response.data = data + webnotes._response.headers["Page Name"] = page_name def render_page(page_name): """get page html""" - set_content_type(page_name) + cache_key = ("page_context:{}" if is_ajax() else "page:{}").format(page_name) + + out = None - if page_name.endswith('.html'): - page_name = page_name[:-5] - html = '' + # try memcache + if can_cache(): + out = webnotes.cache().get_value(cache_key) + if is_ajax(): + out = out.get("data") - if not conf.disable_website_cache: - html = webnotes.cache().get_value("page:" + page_name) - from_cache = True - - if not html: - html = build_page(page_name) - from_cache = False - - if page_name=="error": - html = html.replace("%(error)s", webnotes.get_traceback()) - elif "text/html" in webnotes._response.headers["Content-Type"]: - comments = "\npage:"+page_name+\ - "\nload status: " + (from_cache and "cache" or "fresh") - html += """\n""" % webnotes.utils.cstr(comments) - - return html + if out: + webnotes._response.headers["From Cache"] = True + return out -def set_content_type(page_name): - webnotes._response.headers["Content-Type"] = "text/html; charset: utf-8" + return build(page_name) - if "." in page_name and not page_name.endswith(".html"): - content_type, encoding = mimetypes.guess_type(page_name) - webnotes._response.headers["Content-Type"] = content_type - -def build_page(page_name): +def build(page_name): if not webnotes.conn: webnotes.connect() - - if page_name=="index": - page_name = get_home_page() + + build_method = (build_json if is_ajax() else build_page) try: - sitemap_options = webnotes.doc("Website Sitemap", page_name).fields - page_options = webnotes.doc("Website Sitemap Config", - sitemap_options.get("website_sitemap_config")).fields.update({ - "page_name":sitemap_options.page_name, - "docname":sitemap_options.docname - }) + return build_method(page_name) + except webnotes.DoesNotExistError: hooks = webnotes.get_hooks() if hooks.website_catch_all: - return build_page(hooks.website_catch_all[0]) + return build_method(hooks.website_catch_all[0]) else: - return build_page("404") - - page_options["page_name"] = page_name + return build_method("404") - no_cache = page_options.get("no_cache") - - # if generator, then load bean, pass arguments - if page_options.get("page_or_generator")=="Generator": - bean = webnotes.bean(page_options.get("ref_doctype"), page_options["docname"]) - bean.run_method("get_context") - - context = webnotes._dict(bean.doc.fields) - context["obj"] = bean.get_controller() - else: - # page - context = webnotes._dict({ 'name': page_name }) - if page_options.get("controller"): - module = webnotes.get_module(page_options.get("controller")) - if module and hasattr(module, "get_context"): - context.update(module.get_context()) +def build_json(page_name): + return get_context(page_name).data +def build_page(page_name): + context = get_context(page_name) context.update(get_website_settings()) - - jenv = webnotes.get_jenv() - context["base_template"] = jenv.get_template("templates/base.html") - template_name = page_options['template_path'] - context["_"] = webnotes._ - html = jenv.get_template(template_name).render(context) + jenv = webnotes.get_jenv() + html = jenv.get_template(context.base_template_path).render(context) - if not no_cache: + if can_cache(context.no_cache): webnotes.cache().set_value("page:" + page_name, html) + return html + +def get_context(page_name): + context = None + cache_key = "page_context:{}".format(page_name) + + # try from memcache + if can_cache(): + context = webnotes.cache().get_value(cache_key) + + if not context: + sitemap_options = build_sitemap_options(page_name) + context = build_context(sitemap_options) + if can_cache(context.no_cache): + webnotes.cache().set_value(cache_key, context) + + context.update(context.data or {}) + return context + +def build_sitemap_options(page_name): + sitemap_options = webnotes.doc("Website Sitemap", page_name).fields + + # only non default fields + for fieldname in default_fields: + if fieldname in sitemap_options: + del sitemap_options[fieldname] + + sitemap_config = webnotes.doc("Website Sitemap Config", + sitemap_options.get("website_sitemap_config")).fields + + # get sitemap config fields too + for fieldname in ("base_template_path", "template_path", "controller", "no_cache", "no_sitemap", + "page_name_field", "condition_field"): + sitemap_options[fieldname] = sitemap_config.get(fieldname) + + # establish hierarchy + sitemap_options.parents = webnotes.conn.sql("""select name, page_title from `tabWebsite Sitemap` + where lft < %s and rgt > %s order by lft asc""", (sitemap_options.lft, sitemap_options.rgt), as_dict=True) + + sitemap_options.children = webnotes.conn.sql("""select * from `tabWebsite Sitemap` + where parent_website_sitemap=%s""", (sitemap_options.page_name,)) + + # determine templates to be used + if not sitemap_options.base_template_path: + sitemap_options.base_template_path = "templates/base.html" + sitemap_options.template = webnotes.get_jenv().get_template(sitemap_options.template_path) + + return sitemap_options + +def build_context(sitemap_options): + """get_context method of bean or module is supposed to render content templates and push it into context""" + context = webnotes._dict({ "_": webnotes._ }) + context.update(sitemap_options) + + if sitemap_options.get("controller"): + module = webnotes.get_module(sitemap_options.get("controller")) + if module and hasattr(module, "get_context"): + context.data = module.get_context(context) or {} + + return context + +def can_cache(no_cache=False): + return not (webnotes.conf.disable_website_cache or no_cache) + def get_home_page(): return webnotes.cache().get_value("home_page", \ lambda: webnotes.conn.get_value("Website Settings", None, "home_page") or "login") def get_website_settings(): - from webnotes.utils import get_request_site_address, encode, cint - from urllib import quote - + # TODO Cache this hooks = webnotes.get_hooks() all_top_items = webnotes.conn.sql("""\ @@ -177,6 +209,43 @@ def get_website_settings(): context.web_include_css = hooks.web_include_css or [] return context + +def is_ajax(): + return webnotes.get_request_header("X-Requested-With")=="XMLHttpRequest" + +def scrub_page_name(page_name): + if not page_name: + page_name = "index" + + if "/" in page_name: + page_name = page_name.split("/")[0] + + if page_name.endswith('.html'): + page_name = page_name[:-5] + + return page_name + +def insert_traceback(data): + if isinstance(data, dict): + data["error"] = webnotes.get_traceback() + else: + data = data.replace("%(error)s", webnotes.get_traceback()) + + return data + +def set_content_type(data, page_name): + if isinstance(data, dict): + webnotes._response.headers["Content-Type"] = "application/json; charset: utf-8" + data = json.dumps(data) + return data + + webnotes._response.headers["Content-Type"] = "text/html; charset: utf-8" + + if "." in page_name and not page_name.endswith(".html"): + content_type, encoding = mimetypes.guess_type(page_name) + webnotes._response.headers["Content-Type"] = content_type + + return data def clear_cache(page_name=None): if page_name: @@ -321,3 +390,6 @@ def get_hex_shade(color, percent): percent = percent * 2 return p(r) + p(g) + p(b) + +def get_access(sitemap): + pass \ No newline at end of file