From 8ab1345d9abbed15910cb1efbd0af622f9ece58b Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Wed, 7 May 2014 17:57:00 +0530 Subject: [PATCH] started standard lists and views [wip] for portal --- frappe/model/meta.py | 14 ++++- frappe/templates/pages/list.html | 84 +++++++++++++++++++++++++++++ frappe/templates/pages/list.py | 46 ++++++++++++++++ frappe/templates/pages/message.html | 2 +- frappe/templates/pages/view.html | 40 ++++++++++++++ frappe/templates/pages/view.py | 14 +++++ frappe/website/js/website.js | 3 ++ frappe/website/render.py | 40 ++++++++++++-- frappe/widgets/search.py | 2 +- 9 files changed, 239 insertions(+), 6 deletions(-) create mode 100644 frappe/templates/pages/list.html create mode 100644 frappe/templates/pages/list.py create mode 100644 frappe/templates/pages/view.html create mode 100644 frappe/templates/pages/view.py diff --git a/frappe/model/meta.py b/frappe/model/meta.py index f4f2c099a8..6a5d001202 100644 --- a/frappe/model/meta.py +++ b/frappe/model/meta.py @@ -99,6 +99,18 @@ class Meta(Document): def get_options(self, fieldname): return self.get_field(fieldname).options + def get_search_fields(self): + search_fields = self.search_fields or "name" + search_fields = [d.strip() for d in search_fields.split(",")] + if "name" not in search_fields: + search_fields.append("name") + + return search_fields + + def get_list_fields(self): + return ["name"] + [d.fieldname \ + for d in self.fields if (d.in_list_view and d.fieldtype in type_map)] + def process(self): # don't process for special doctypes # prevent's circular dependency @@ -203,7 +215,7 @@ doctype_table_fields = [ def is_single(doctype): try: return frappe.db.get_value("DocType", doctype, "issingle") - except IndexError, e: + except IndexError: raise Exception, 'Cannot determine whether %s is single' % doctype def get_parent_dt(dt): diff --git a/frappe/templates/pages/list.html b/frappe/templates/pages/list.html new file mode 100644 index 0000000000..11a5b15512 --- /dev/null +++ b/frappe/templates/pages/list.html @@ -0,0 +1,84 @@ +{% block title %}{{ type }} {{ _("List") }}{% endblock %} + +{% block header %} +

{{ type }} {{ _("List") }}

+{% endblock %} + +{% block content %} + +
+
+ +
+
+
+{% if txt %} +
Results filtered by {{ txt }}. ×
+{% endif %} +
+{% for item in items %} +
+ {{ item }} +
+{% endfor %} +
+
+ +
+{% endblock %} + +{% block script %} + +{% endblock %} diff --git a/frappe/templates/pages/list.py b/frappe/templates/pages/list.py new file mode 100644 index 0000000000..92a10c3421 --- /dev/null +++ b/frappe/templates/pages/list.py @@ -0,0 +1,46 @@ +# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors +# MIT License. See license.txt + +from __future__ import unicode_literals +import frappe, os +from frappe.modules import get_doc_path +from jinja2 import Environment, Template, FileSystemLoader + +no_cache = 1 +no_sitemap = 1 + +def get_context(context): + context.type = frappe.local.form_dict.type + context.txt = frappe.local.form_dict.txt + context.update(get_items(context.type, context.txt)) + return context + +@frappe.whitelist(allow_guest=True) +def get_items(type, txt, limit_start=0): + meta = frappe.get_meta(type) + filters, or_filters = [], [] + out = frappe._dict() + + if txt: + if meta.search_fields: + for f in meta.get_search_fields(): + or_filters.append([type, f.strip(), "like", "%" + txt + "%"]) + else: + filters.append([type, "name", "like", "%" + txt + "%"]) + + + out.raw_items = frappe.get_list(type, fields = meta.get_list_fields(), + filters=filters, or_filters = or_filters, limit_start=limit_start, + limit_page_length = 20) + template_path = os.path.join(get_doc_path(meta.module, "DocType", meta.name), "list_item.html") + + if os.path.exists(template_path): + env = Environment(loader = FileSystemLoader(".")) + template = env.get_template(template_path) + else: + template = Template("""
+ {{ item.name }}
""") + + out.items = [template.render(item=i, doctype=type) for i in out.raw_items] + + return out diff --git a/frappe/templates/pages/message.html b/frappe/templates/pages/message.html index df8f6ac7af..2c70bf8457 100644 --- a/frappe/templates/pages/message.html +++ b/frappe/templates/pages/message.html @@ -7,4 +7,4 @@

{{ message }}

-{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/frappe/templates/pages/view.html b/frappe/templates/pages/view.html new file mode 100644 index 0000000000..699e1b12e8 --- /dev/null +++ b/frappe/templates/pages/view.html @@ -0,0 +1,40 @@ +{% block title %}{{ doc.doctype }} / {{ doc.name }}{% endblock %} + +{% block header %} +

{{ doc.name }}

+

{{ doc.doctype }} +{% endblock %} + +{% block content %} +{% if custom_view %} +{{ custom_view }} +{% else %} +{% for df in meta.fields %} + {% if not df.hidden and not df.permlevel and not df.print_hide %} + {% if df.fieldtype=="Section Break" %} +

{{ df.label or "" }}

+ {% elif df.fieldtype=="Column Break" %} + {% elif df.fieldtype=="Table" %} + + {% else %} +
+
+ {% if df.fieldtype not in ("Image",) %} + + {% endif %} +
+
+ {% if df.fieldtype=="Check" %} + + {% elif df.fieldtype=="Image" %} + + {% else %} + {{ doc[df.fieldname] }} + {% endif %} +
+
+ {% endif %} + {% endif %} +{% endfor %} +{% endif %} +{% endblock %} diff --git a/frappe/templates/pages/view.py b/frappe/templates/pages/view.py new file mode 100644 index 0000000000..e6f31d3146 --- /dev/null +++ b/frappe/templates/pages/view.py @@ -0,0 +1,14 @@ +# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors +# MIT License. See license.txt + +from __future__ import unicode_literals +import frappe + +no_cache = 1 +no_sitemap = 1 + +def get_context(context): + return { + "doc": frappe.get_doc(frappe.local.form_dict.doctype, frappe.local.form_dict.name), + "meta": frappe.get_meta(frappe.local.form_dict.doctype) + } diff --git a/frappe/website/js/website.js b/frappe/website/js/website.js index fba7a35934..ee399ca7e0 100644 --- a/frappe/website/js/website.js +++ b/frappe/website/js/website.js @@ -221,6 +221,9 @@ $.extend(frappe, { if ( event.which > 1 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey ) return; + if (link.getAttribute("target")) + return; + // Ignore cross origin links if ( location.protocol !== link.protocol || location.hostname !== link.hostname ) return; diff --git a/frappe/website/render.py b/frappe/website/render.py index c512eb1768..ef16616bfe 100644 --- a/frappe/website/render.py +++ b/frappe/website/render.py @@ -8,7 +8,7 @@ from werkzeug.wrappers import Response from frappe.website.context import get_context from frappe.website.utils import scrub_relative_urls, get_home_page, can_cache -from frappe.website.permissions import get_access, clear_permissions +from frappe.website.permissions import clear_permissions class PageNotFoundError(Exception): pass @@ -18,9 +18,25 @@ def render(path, http_status_code=None): try: data = render_page(path) - except frappe.DoesNotExistError, e: - path = "404" + doctype, name = get_doctype_from_path(path) + if doctype and name: + path = "view" + frappe.local.form_dict.doctype = doctype + frappe.local.form_dict.name = name + elif doctype: + path = "list" + frappe.local.form_dict.type = doctype + else: + path = "404" + http_status_code = e.http_status_code + + data = render_page(path) + + except frappe.PermissionError, e: + path = "message" + frappe.local.message = "Did you log out?" + frappe.local.message_title = "Not Permitted" data = render_page(path) http_status_code = e.http_status_code @@ -31,6 +47,24 @@ def render(path, http_status_code=None): return build_response(path, data, http_status_code or 200) +def get_doctype_from_path(path): + doctypes = [d[0] for d in frappe.get_list("DocType", as_list=True)] + + parts = path.split("/") + + doctype = parts[0] + name = parts[1] if len(parts) > 1 else None + + if doctype in doctypes: + return doctype, name + + # try scrubbed + doctype = doctype.replace("_", " ").title() + if doctype in doctypes: + return doctype, name + + return None, None + def build_response(path, data, http_status_code): # build response response = Response() diff --git a/frappe/widgets/search.py b/frappe/widgets/search.py index 3a4200d7dd..537e263868 100644 --- a/frappe/widgets/search.py +++ b/frappe/widgets/search.py @@ -61,7 +61,7 @@ def search_widget(doctype, txt, query=None, searchfield=None, start=0, # build from doctype if txt: if meta.search_fields: - for f in meta.search_fields.split(","): + for f in meta.get_search_fields(): or_filters.append([doctype, f.strip(), "like", "%" + txt + "%"]) else: filters.append([doctype, searchfield or "name", "like",