diff --git a/frappe/core/doctype/docfield/docfield.json b/frappe/core/doctype/docfield/docfield.json
index f2f954c810..becf114966 100644
--- a/frappe/core/doctype/docfield/docfield.json
+++ b/frappe/core/doctype/docfield/docfield.json
@@ -1,5 +1,6 @@
{
"allow_copy": 0,
+ "allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"autoname": "hash",
@@ -470,7 +471,7 @@
"columns": 0,
"description": "For Links, enter the DocType as range.\nFor Select, enter list of Options, each on a new line.",
"fieldname": "options",
- "fieldtype": "Text",
+ "fieldtype": "Small Text",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
@@ -1278,6 +1279,7 @@
"unique": 0
}
],
+ "has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 1,
@@ -1288,7 +1290,7 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
- "modified": "2017-02-22 21:43:00.771400",
+ "modified": "2017-03-03 16:18:13.523592",
"modified_by": "Administrator",
"module": "Core",
"name": "DocField",
diff --git a/frappe/core/doctype/docperm/docperm.json b/frappe/core/doctype/docperm/docperm.json
index 8e9273118e..b1ecf894eb 100644
--- a/frappe/core/doctype/docperm/docperm.json
+++ b/frappe/core/doctype/docperm/docperm.json
@@ -1,5 +1,6 @@
{
"allow_copy": 0,
+ "allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"autoname": "hash",
@@ -8,6 +9,7 @@
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
+ "document_type": "Setup",
"editable_grid": 1,
"fields": [
{
@@ -21,6 +23,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
+ "in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Role and Level",
@@ -48,6 +51,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
+ "in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Role",
@@ -81,6 +85,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
+ "in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Apply User Permissions",
@@ -109,6 +114,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
+ "in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "If user is the owner",
@@ -137,6 +143,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
+ "in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
@@ -164,6 +171,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
+ "in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Level",
@@ -197,6 +205,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
+ "in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "User Permission DocTypes",
@@ -224,6 +233,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
+ "in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Permissions",
@@ -252,6 +262,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
+ "in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Read",
@@ -284,6 +295,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
+ "in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Write",
@@ -316,6 +328,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
+ "in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Create",
@@ -348,6 +361,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
+ "in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Delete",
@@ -375,6 +389,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
+ "in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
@@ -401,6 +416,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
+ "in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Submit",
@@ -432,6 +448,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
+ "in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Cancel",
@@ -463,6 +480,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
+ "in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Amend",
@@ -494,6 +512,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
+ "in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Additional Permissions",
@@ -522,6 +541,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
+ "in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Report",
@@ -552,6 +572,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
+ "in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Export",
@@ -579,6 +600,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
+ "in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Import",
@@ -607,6 +629,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
+ "in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Set User Permissions",
@@ -634,6 +657,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
+ "in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
@@ -661,6 +685,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
+ "in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Share",
@@ -690,6 +715,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
+ "in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Print",
@@ -718,6 +744,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
+ "in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Email",
@@ -735,6 +762,7 @@
"unique": 0
}
],
+ "has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 1,
@@ -745,7 +773,7 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
- "modified": "2017-01-11 04:21:44.249780",
+ "modified": "2017-03-03 16:18:18.890031",
"modified_by": "Administrator",
"module": "Core",
"name": "DocPerm",
@@ -754,6 +782,7 @@
"quick_entry": 0,
"read_only": 0,
"read_only_onload": 0,
+ "show_name_in_global_search": 0,
"sort_order": "ASC",
"track_changes": 0,
"track_seen": 0
diff --git a/frappe/core/doctype/doctype/boilerplate/controller.js b/frappe/core/doctype/doctype/boilerplate/controller.js
index 6a015936d1..87c69d29ad 100644
--- a/frappe/core/doctype/doctype/boilerplate/controller.js
+++ b/frappe/core/doctype/doctype/boilerplate/controller.js
@@ -1,4 +1,4 @@
-// Copyright (c) 2016, {app_publisher} and contributors
+// Copyright (c) {year}, {app_publisher} and contributors
// For license information, please see license.txt
frappe.ui.form.on('{doctype}', {{
diff --git a/frappe/core/doctype/doctype/boilerplate/controller.py b/frappe/core/doctype/doctype/boilerplate/controller.py
index 7a320b3ca3..d6af4f15aa 100644
--- a/frappe/core/doctype/doctype/boilerplate/controller.py
+++ b/frappe/core/doctype/doctype/boilerplate/controller.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright (c) 2015, {app_publisher} and contributors
+# Copyright (c) {year}, {app_publisher} and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
diff --git a/frappe/core/doctype/doctype/boilerplate/templates/controller.html b/frappe/core/doctype/doctype/boilerplate/templates/controller.html
new file mode 100644
index 0000000000..412368d9b7
--- /dev/null
+++ b/frappe/core/doctype/doctype/boilerplate/templates/controller.html
@@ -0,0 +1,7 @@
+{{% extends "templates/web.html" %}}
+
+{{% block page_content %}}
+
{{{{ title }}}}
+{{% endblock %}}
+
+
\ No newline at end of file
diff --git a/frappe/core/doctype/doctype/boilerplate/templates/controller_row.html b/frappe/core/doctype/doctype/boilerplate/templates/controller_row.html
new file mode 100644
index 0000000000..3cc8ce2c2d
--- /dev/null
+++ b/frappe/core/doctype/doctype/boilerplate/templates/controller_row.html
@@ -0,0 +1,4 @@
+
+
\ No newline at end of file
diff --git a/frappe/core/doctype/doctype/boilerplate/test_controller.py b/frappe/core/doctype/doctype/boilerplate/test_controller.py
index b085ff3d0c..44e030bd0e 100644
--- a/frappe/core/doctype/doctype/boilerplate/test_controller.py
+++ b/frappe/core/doctype/doctype/boilerplate/test_controller.py
@@ -1,12 +1,10 @@
# -*- coding: utf-8 -*-
-# Copyright (c) 2015, {app_publisher} and Contributors
+# Copyright (c) {year}, {app_publisher} and Contributors
# See license.txt
from __future__ import unicode_literals
import frappe
import unittest
-# test_records = frappe.get_test_records('{doctype}')
-
class Test{classname}(unittest.TestCase):
pass
diff --git a/frappe/core/doctype/doctype/doctype.json b/frappe/core/doctype/doctype/doctype.json
index 49dd96a21b..14851244ea 100644
--- a/frappe/core/doctype/doctype/doctype.json
+++ b/frappe/core/doctype/doctype/doctype.json
@@ -1,5 +1,6 @@
{
"allow_copy": 0,
+ "allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 1,
"autoname": "Prompt",
@@ -172,10 +173,8 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
- "default": "1",
- "depends_on": "eval:!doc.istable && !doc.issingle",
- "fieldname": "quick_entry",
- "fieldtype": "Check",
+ "fieldname": "cb01",
+ "fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
@@ -183,11 +182,9 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
- "label": "Quick Entry",
"length": 0,
"no_copy": 0,
"permlevel": 0,
- "precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
@@ -204,8 +201,8 @@
"collapsible": 0,
"columns": 0,
"default": "1",
- "depends_on": "eval:!doc.istable",
- "fieldname": "track_changes",
+ "depends_on": "eval:!doc.istable && !doc.issingle",
+ "fieldname": "quick_entry",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
@@ -214,7 +211,7 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
- "label": "Track Changes",
+ "label": "Quick Entry",
"length": 0,
"no_copy": 0,
"permlevel": 0,
@@ -234,67 +231,10 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
- "fieldname": "cb01",
- "fieldtype": "Column Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
- {
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "description": "",
- "fieldname": "document_type",
- "fieldtype": "Select",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Show in Module Section",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "document_type",
- "oldfieldtype": "Select",
- "options": "\nDocument\nSetup\nSystem\nOther",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
- {
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "icon",
- "fieldtype": "Data",
+ "default": "1",
+ "depends_on": "eval:!doc.istable",
+ "fieldname": "track_changes",
+ "fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
@@ -302,10 +242,11 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
- "label": "Icon",
+ "label": "Track Changes",
"length": 0,
"no_copy": 0,
"permlevel": 0,
+ "precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
@@ -418,7 +359,7 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
- "label": "Plugin",
+ "label": "App",
"length": 0,
"no_copy": 0,
"permlevel": 0,
@@ -587,8 +528,9 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
- "fieldname": "description",
- "fieldtype": "Small Text",
+ "depends_on": "",
+ "fieldname": "column_break_15",
+ "fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
@@ -596,11 +538,8 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
- "label": "Description",
"length": 0,
"no_copy": 0,
- "oldfieldname": "description",
- "oldfieldtype": "Text",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
@@ -617,9 +556,8 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
- "depends_on": "",
- "fieldname": "column_break_15",
- "fieldtype": "Column Break",
+ "fieldname": "description",
+ "fieldtype": "Small Text",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
@@ -627,8 +565,11 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
+ "label": "Description",
"length": 0,
"no_copy": 0,
+ "oldfieldname": "description",
+ "oldfieldtype": "Text",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
@@ -645,10 +586,8 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
- "depends_on": "eval:!doc.istable",
- "description": "Show this field as title",
- "fieldname": "title_field",
- "fieldtype": "Data",
+ "fieldname": "view_settings",
+ "fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
@@ -656,10 +595,11 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
- "label": "Title Field",
+ "label": "View Settings",
"length": 0,
"no_copy": 0,
"permlevel": 0,
+ "precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
@@ -676,7 +616,8 @@
"collapsible": 0,
"columns": 0,
"depends_on": "eval:!doc.istable",
- "fieldname": "search_fields",
+ "description": "",
+ "fieldname": "title_field",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
@@ -685,11 +626,9 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
- "label": "Search Fields",
+ "label": "Title Field",
"length": 0,
"no_copy": 0,
- "oldfieldname": "search_fields",
- "oldfieldtype": "Data",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
@@ -706,8 +645,8 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
- "description": "Must be of type \"Attach Image\"",
- "fieldname": "image_field",
+ "depends_on": "eval:!doc.istable",
+ "fieldname": "search_fields",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
@@ -716,11 +655,12 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
- "label": "Image Field",
+ "label": "Search Fields",
"length": 0,
"no_copy": 0,
+ "oldfieldname": "search_fields",
+ "oldfieldtype": "Data",
"permlevel": 0,
- "precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
@@ -736,10 +676,8 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
- "default": "modified",
- "depends_on": "eval:!doc.istable",
"description": "",
- "fieldname": "sort_field",
+ "fieldname": "image_field",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
@@ -748,10 +686,11 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
- "label": "Sort Field",
+ "label": "Image Field (Must of type \"Attach Image\")",
"length": 0,
"no_copy": 0,
"permlevel": 0,
+ "precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
@@ -767,10 +706,10 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
- "default": "DESC",
"depends_on": "eval:!doc.istable",
- "fieldname": "sort_order",
- "fieldtype": "Select",
+ "description": "Comments and Communications will be associated with this linked document",
+ "fieldname": "timeline_field",
+ "fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
@@ -778,11 +717,11 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
- "label": "Sort Order",
+ "label": "Timeline Field",
"length": 0,
"no_copy": 0,
- "options": "ASC\nDESC",
"permlevel": 0,
+ "precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
@@ -798,10 +737,8 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
- "depends_on": "eval:!doc.istable",
- "description": "Comments and Communications will be associated with this linked document",
- "fieldname": "timeline_field",
- "fieldtype": "Data",
+ "fieldname": "column_break_29",
+ "fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
@@ -809,7 +746,6 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
- "label": "Timeline Field",
"length": 0,
"no_copy": 0,
"permlevel": 0,
@@ -829,9 +765,9 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
- "depends_on": "eval:!doc.istable",
- "fieldname": "sb2",
- "fieldtype": "Section Break",
+ "description": "",
+ "fieldname": "document_type",
+ "fieldtype": "Select",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
@@ -839,9 +775,12 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
- "label": "Permission Rules",
+ "label": "Show in Module Section",
"length": 0,
"no_copy": 0,
+ "oldfieldname": "document_type",
+ "oldfieldtype": "Select",
+ "options": "\nDocument\nSetup\nSystem\nOther",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
@@ -858,9 +797,8 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
- "depends_on": "",
- "fieldname": "permissions",
- "fieldtype": "Table",
+ "fieldname": "icon",
+ "fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
@@ -868,12 +806,9 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
- "label": "Permissions",
+ "label": "Icon",
"length": 0,
"no_copy": 0,
- "oldfieldname": "permissions",
- "oldfieldtype": "Table",
- "options": "DocPerm",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
@@ -890,9 +825,8 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
- "depends_on": "eval:!doc.istable",
- "fieldname": "sb3",
- "fieldtype": "Section Break",
+ "fieldname": "track_seen",
+ "fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
@@ -900,9 +834,11 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
+ "label": "Track Seen",
"length": 0,
"no_copy": 0,
"permlevel": 0,
+ "precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
@@ -918,8 +854,8 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
- "fieldname": "cb30",
- "fieldtype": "Column Break",
+ "fieldname": "read_only_onload",
+ "fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
@@ -927,9 +863,11 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
- "label": "Permissions Settings",
+ "label": "Show Print First",
"length": 0,
"no_copy": 0,
+ "oldfieldname": "read_only_onload",
+ "oldfieldtype": "Check",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
@@ -946,7 +884,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
- "fieldname": "in_create",
+ "fieldname": "hide_heading",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
@@ -955,10 +893,10 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
- "label": "User Cannot Create",
+ "label": "Hide Heading",
"length": 0,
"no_copy": 0,
- "oldfieldname": "in_create",
+ "oldfieldname": "hide_heading",
"oldfieldtype": "Check",
"permlevel": 0,
"print_hide": 0,
@@ -976,7 +914,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
- "fieldname": "read_only",
+ "fieldname": "hide_toolbar",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
@@ -985,10 +923,10 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
- "label": "User Cannot Search",
+ "label": "Hide Toolbar",
"length": 0,
"no_copy": 0,
- "oldfieldname": "read_only",
+ "oldfieldname": "hide_toolbar",
"oldfieldtype": "Check",
"permlevel": 0,
"print_hide": 0,
@@ -1006,7 +944,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
- "fieldname": "is_submittable",
+ "fieldname": "allow_copy",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
@@ -1015,9 +953,11 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
- "label": "Is Submittable",
+ "label": "Hide Copy",
"length": 0,
"no_copy": 0,
+ "oldfieldname": "allow_copy",
+ "oldfieldtype": "Check",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
@@ -1034,8 +974,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
- "description": "Allow Import via Data Import Tool",
- "fieldname": "allow_import",
+ "fieldname": "show_name_in_global_search",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
@@ -1044,10 +983,11 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
- "label": "Allow Import",
+ "label": "Make \"name\" searchable in Global Search",
"length": 0,
"no_copy": 0,
"permlevel": 0,
+ "precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
@@ -1063,8 +1003,9 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
- "fieldname": "allow_rename",
- "fieldtype": "Check",
+ "depends_on": "eval:!doc.istable",
+ "fieldname": "sb2",
+ "fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
@@ -1072,11 +1013,9 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
- "label": "Allow Rename",
+ "label": "Permission Rules",
"length": 0,
"no_copy": 0,
- "oldfieldname": "allow_rename",
- "oldfieldtype": "Check",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
@@ -1093,8 +1032,9 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
- "fieldname": "in_dialog",
- "fieldtype": "Check",
+ "depends_on": "",
+ "fieldname": "permissions",
+ "fieldtype": "Table",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
@@ -1102,11 +1042,12 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
- "label": "In Dialog",
+ "label": "Permissions",
"length": 0,
"no_copy": 0,
- "oldfieldname": "in_dialog",
- "oldfieldtype": "Check",
+ "oldfieldname": "permissions",
+ "oldfieldtype": "Table",
+ "options": "DocPerm",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
@@ -1123,8 +1064,9 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
- "fieldname": "read_only_onload",
- "fieldtype": "Check",
+ "depends_on": "eval:!doc.istable",
+ "fieldname": "sb3",
+ "fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
@@ -1132,11 +1074,8 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
- "label": "Show Print First",
"length": 0,
"no_copy": 0,
- "oldfieldname": "read_only_onload",
- "oldfieldtype": "Check",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
@@ -1153,8 +1092,8 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
- "fieldname": "show_name_in_global_search",
- "fieldtype": "Check",
+ "fieldname": "cb30",
+ "fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
@@ -1162,11 +1101,10 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
- "label": "Make \"name\" searchable in Global Search",
+ "label": "Permissions Settings",
"length": 0,
"no_copy": 0,
"permlevel": 0,
- "precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
@@ -1182,8 +1120,8 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
- "fieldname": "max_attachments",
- "fieldtype": "Int",
+ "fieldname": "is_submittable",
+ "fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
@@ -1191,11 +1129,9 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
- "label": "Max Attachments",
+ "label": "Is Submittable",
"length": 0,
"no_copy": 0,
- "oldfieldname": "max_attachments",
- "oldfieldtype": "Int",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
@@ -1212,8 +1148,9 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
- "fieldname": "cb31",
- "fieldtype": "Column Break",
+ "description": "",
+ "fieldname": "allow_import",
+ "fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
@@ -1221,7 +1158,7 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
- "label": "Other Settings",
+ "label": "Allow Import (via Data Import Tool)",
"length": 0,
"no_copy": 0,
"permlevel": 0,
@@ -1240,7 +1177,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
- "fieldname": "hide_heading",
+ "fieldname": "allow_rename",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
@@ -1249,10 +1186,10 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
- "label": "Hide Heading",
+ "label": "Allow Rename",
"length": 0,
"no_copy": 0,
- "oldfieldname": "hide_heading",
+ "oldfieldname": "allow_rename",
"oldfieldtype": "Check",
"permlevel": 0,
"print_hide": 0,
@@ -1270,8 +1207,8 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
- "fieldname": "hide_toolbar",
- "fieldtype": "Check",
+ "fieldname": "cb31",
+ "fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
@@ -1279,10 +1216,215 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
- "label": "Hide Toolbar",
+ "label": "Other Settings",
"length": 0,
"no_copy": 0,
- "oldfieldname": "hide_toolbar",
+ "permlevel": 0,
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "max_attachments",
+ "fieldtype": "Int",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Max Attachments",
+ "length": 0,
+ "no_copy": 0,
+ "oldfieldname": "max_attachments",
+ "oldfieldtype": "Int",
+ "permlevel": 0,
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "default_print_format",
+ "fieldtype": "Data",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Default Print Format",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "list_view_settings",
+ "fieldtype": "Section Break",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "List View Settings",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "default": "modified",
+ "depends_on": "eval:!doc.istable",
+ "description": "",
+ "fieldname": "sort_field",
+ "fieldtype": "Data",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Sort Field",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "default": "DESC",
+ "depends_on": "eval:!doc.istable",
+ "fieldname": "sort_order",
+ "fieldtype": "Select",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Sort Order",
+ "length": 0,
+ "no_copy": 0,
+ "options": "ASC\nDESC",
+ "permlevel": 0,
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "column_break_47",
+ "fieldtype": "Column Break",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "read_only",
+ "fieldtype": "Check",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "User Cannot Search",
+ "length": 0,
+ "no_copy": 0,
+ "oldfieldname": "read_only",
"oldfieldtype": "Check",
"permlevel": 0,
"print_hide": 0,
@@ -1300,7 +1442,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
- "fieldname": "allow_copy",
+ "fieldname": "in_create",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
@@ -1309,10 +1451,10 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
- "label": "Hide Copy",
+ "label": "User Cannot Create",
"length": 0,
"no_copy": 0,
- "oldfieldname": "allow_copy",
+ "oldfieldname": "in_create",
"oldfieldtype": "Check",
"permlevel": 0,
"print_hide": 0,
@@ -1330,7 +1472,37 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
- "fieldname": "track_seen",
+ "fieldname": "web_view",
+ "fieldtype": "Section Break",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Web View",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "default": "0",
+ "fieldname": "has_web_view",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
@@ -1339,7 +1511,7 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
- "label": "Track Seen",
+ "label": "Has Web View",
"length": 0,
"no_copy": 0,
"permlevel": 0,
@@ -1359,7 +1531,67 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
- "fieldname": "default_print_format",
+ "default": "0",
+ "depends_on": "has_web_view",
+ "fieldname": "allow_guest_to_view",
+ "fieldtype": "Check",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Allow Guest to View",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "column_break_53",
+ "fieldtype": "Column Break",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "depends_on": "has_web_view",
+ "fieldname": "route",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
@@ -1368,10 +1600,11 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
- "label": "Default Print Format",
+ "label": "Route",
"length": 0,
"no_copy": 0,
"permlevel": 0,
+ "precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
@@ -1387,6 +1620,37 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "default": "",
+ "depends_on": "has_web_view",
+ "fieldname": "is_published_field",
+ "fieldtype": "Data",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Is Published Field",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 1,
+ "columns": 0,
"fieldname": "advanced",
"fieldtype": "Section Break",
"hidden": 0,
@@ -1444,6 +1708,7 @@
"unique": 0
}
],
+ "has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"icon": "fa fa-bolt",
@@ -1455,7 +1720,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
- "modified": "2017-02-17 16:41:27.613879",
+ "modified": "2017-03-03 15:55:30.792653",
"modified_by": "Administrator",
"module": "Core",
"name": "DocType",
diff --git a/frappe/core/doctype/doctype/doctype.py b/frappe/core/doctype/doctype/doctype.py
index 09c883b502..40f883a5be 100644
--- a/frappe/core/doctype/doctype/doctype.py
+++ b/frappe/core/doctype/doctype/doctype.py
@@ -15,6 +15,7 @@ from frappe.custom.doctype.property_setter.property_setter import make_property_
from frappe.desk.notifications import delete_notification_count_for
from frappe.modules import make_boilerplate
from frappe.model.db_schema import validate_column_name
+import frappe.website.render
class InvalidFieldNameError(frappe.ValidationError): pass
@@ -122,15 +123,13 @@ class DocType(Document):
def validate_website(self):
"""Ensure that website generator has field 'route'"""
- from frappe.model.base_document import get_controller
- try:
- controller = get_controller(self.name)
- except:
- controller = None
-
- if controller and getattr(controller, 'website', None):
+ if self.has_web_view:
+ # route field must be present
if not 'route' in [d.fieldname for d in self.fields]:
- frappe.throw('Field "route" is mandatory for Website Generator pages', title='Missing Field')
+ frappe.throw('Field "route" is mandatory for Web Views', title='Missing Field')
+
+ # clear website cache
+ frappe.website.render.clear_cache()
def change_modified_of_parent(self):
"""Change the timestamp of parent DocType if the current one is a child to clear caches."""
@@ -297,6 +296,10 @@ class DocType(Document):
if not self.istable:
make_boilerplate("controller.js", self.as_dict())
+ if self.has_web_view:
+ make_boilerplate('templates/controller.html', self.as_dict())
+ make_boilerplate('templates/controller_row.html', self.as_dict())
+
def make_amendable(self):
"""If is_submittable is set, add amended_from docfields."""
if self.is_submittable:
@@ -497,6 +500,12 @@ def validate_fields(meta):
if df[0].fieldtype != 'Attach Image':
frappe.throw(_("Image field must be of type Attach Image"), InvalidFieldNameError)
+ def check_is_published_field(meta):
+ if not meta.is_published_field:
+ return
+
+ if meta.is_published_field not in fieldname_list:
+ frappe.throw(_("Is Published Field must be a valid fieldname"), InvalidFieldNameError)
def check_timeline_field(meta):
if not meta.timeline_field:
@@ -549,6 +558,7 @@ def validate_fields(meta):
check_search_fields(meta)
check_title_field(meta)
check_timeline_field(meta)
+ check_is_published_field(meta)
check_sort_field(meta)
def validate_permissions_for_doctype(doctype, for_remove=False):
diff --git a/frappe/data/Framework.sql b/frappe/data/Framework.sql
index bb4bf7027e..6aed34520c 100644
--- a/frappe/data/Framework.sql
+++ b/frappe/data/Framework.sql
@@ -141,7 +141,6 @@ CREATE TABLE `tabDocType` (
`max_attachments` int(11) NOT NULL DEFAULT 0,
`print_outline` varchar(255) DEFAULT NULL,
`read_only_onload` int(1) NOT NULL DEFAULT 0,
- `in_dialog` int(1) NOT NULL DEFAULT 0,
`document_type` varchar(255) DEFAULT NULL,
`icon` varchar(255) DEFAULT NULL,
`tag_fields` varchar(255) DEFAULT NULL,
@@ -155,6 +154,10 @@ CREATE TABLE `tabDocType` (
`custom` int(1) NOT NULL DEFAULT 0,
`beta` int(1) NOT NULL DEFAULT 0,
`image_view` int(1) NOT NULL DEFAULT 0,
+ `has_web_view` int(1) NOT NULL DEFAULT 0,
+ `allow_guest_to_view` int(1) NOT NULL DEFAULT 0,
+ `route` varchar(255) DEFAULT NULL,
+ `is_published_field` varchar(255) DEFAULT NULL,
PRIMARY KEY (`name`),
KEY `parent` (`parent`)
) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
diff --git a/frappe/model/meta.py b/frappe/model/meta.py
index 055a1dc366..6435646101 100644
--- a/frappe/model/meta.py
+++ b/frappe/model/meta.py
@@ -16,7 +16,7 @@ Example:
'''
from __future__ import unicode_literals
-import frappe, json
+import frappe, json, os
from frappe.utils import cstr, cint
from frappe.model import default_fields, no_value_fields, optional_fields
from frappe.model.document import Document
@@ -352,6 +352,20 @@ class Meta(Document):
return data
+ def get_row_template(self):
+ return self.get_web_template(suffix='_row')
+
+ def get_web_template(self, suffix=''):
+ '''Returns the relative path of the row template for this doctype'''
+ module_name = frappe.scrub(self.module)
+ doctype = frappe.scrub(self.name)
+ template_path = frappe.get_module_path(module_name, 'doctype',
+ doctype, 'templates', doctype + suffix + '.html')
+ if os.path.exists(template_path):
+ return '{module_name}/doctype/{doctype_name}/templates/{doctype_name}{suffix}.html'.format(
+ module_name = module_name, doctype_name = doctype, suffix=suffix)
+ return None
+
doctype_table_fields = [
frappe._dict({"fieldname": "fields", "options": "DocField"}),
frappe._dict({"fieldname": "permissions", "options": "DocPerm"})
diff --git a/frappe/modules/utils.py b/frappe/modules/utils.py
index 6b09217444..2d61234473 100644
--- a/frappe/modules/utils.py
+++ b/frappe/modules/utils.py
@@ -19,12 +19,11 @@ def export_module_json(doc, is_standard, module):
if (not frappe.flags.in_import and getattr(frappe.get_conf(),'developer_mode', 0)
and is_standard):
from frappe.modules.export_file import export_to_files
- from frappe.modules import get_module_path
# json
export_to_files(record_list=[[doc.doctype, doc.name]], record_module=module)
- path = os.path.join(get_module_path(module), scrub(doc.doctype),
+ path = os.path.join(frappe.get_module_path(module), scrub(doc.doctype),
scrub(doc.name), scrub(doc.name))
return path
@@ -209,6 +208,8 @@ def make_boilerplate(template, doc, opts=None):
template_name = template.replace("controller", scrub(doc.name))
target_file_path = os.path.join(target_path, template_name)
+ if not doc: doc = {}
+
app_publisher = get_app_publisher(doc.module)
if not os.path.exists(target_file_path):
@@ -219,6 +220,9 @@ def make_boilerplate(template, doc, opts=None):
with open(os.path.join(get_module_path("core"), "doctype", scrub(doc.doctype),
"boilerplate", template), 'r') as source:
target.write(frappe.utils.encode(
- frappe.utils.cstr(source.read()).format(app_publisher=app_publisher,
- classname=doc.name.replace(" ", ""), doctype=doc.name, **opts)
+ frappe.utils.cstr(source.read()).format(
+ app_publisher=app_publisher,
+ year=frappe.utils.nowdate()[:4],
+ classname=doc.name.replace(" ", ""),
+ doctype=doc.name, **opts)
))
diff --git a/frappe/patches.txt b/frappe/patches.txt
index 51727dab73..c7f7e06f98 100644
--- a/frappe/patches.txt
+++ b/frappe/patches.txt
@@ -6,9 +6,9 @@ frappe.patches.v7_1.rename_scheduler_log_to_error_log
frappe.patches.v6_1.rename_file_data
frappe.patches.v7_0.re_route #2016-06-27
frappe.patches.v7_2.remove_in_filter
-execute:frappe.reload_doc('core', 'doctype', 'doctype', force=True) #2016-10-17
-execute:frappe.reload_doc('core', 'doctype', 'docfield', force=True) #2017-01-06
-execute:frappe.reload_doc('core', 'doctype', 'docperm') #2014-06-24
+execute:frappe.reload_doc('core', 'doctype', 'doctype', force=True) #2017-03-03
+execute:frappe.reload_doc('core', 'doctype', 'docfield', force=True) #2017-03-03
+execute:frappe.reload_doc('core', 'doctype', 'docperm') #2017-03-03
execute:frappe.reload_doc('core', 'doctype', 'custom_docperm')
frappe.patches.v7_2.setup_custom_perms #2017-01-19
execute:frappe.reload_doc('core', 'doctype', 'role')
diff --git a/frappe/website/context.py b/frappe/website/context.py
index 35a1217919..3a632ce703 100644
--- a/frappe/website/context.py
+++ b/frappe/website/context.py
@@ -83,6 +83,9 @@ def build_context(context):
if ret:
context.update(ret)
+ if not context.template:
+ context.template = context.doc.meta.get_web_template()
+
for prop in ("no_cache", "no_sitemap"):
if not prop in context:
context[prop] = getattr(context.doc, prop, False)
diff --git a/frappe/website/render.py b/frappe/website/render.py
index 7cf2cf1752..dda400c965 100644
--- a/frappe/website/render.py
+++ b/frappe/website/render.py
@@ -169,7 +169,7 @@ def resolve_path(path):
def resolve_from_map(path):
m = Map([Rule(r["from_route"], endpoint=r["to_route"], defaults=r.get("defaults"))
- for r in frappe.get_hooks("website_route_rules")])
+ for r in get_website_rules()])
urls = m.bind_to_environ(frappe.local.request.environ)
try:
endpoint, args = urls.match("/" + path)
@@ -184,6 +184,18 @@ def resolve_from_map(path):
return path
+def get_website_rules():
+ '''Get website route rules from hooks and DocType route'''
+ def _get():
+ rules = frappe.get_hooks("website_route_rules")
+ for d in frappe.get_all('DocType', 'name, route', dict(has_web_view=1)):
+ if d.route:
+ rules.append(dict(from_route = '/' + d.route.strip('/'), to_route=d.name))
+
+ return rules
+
+ return frappe.cache().get_value('website_route_rules', _get)
+
def set_content_type(response, data, path):
if isinstance(data, dict):
response.mimetype = 'application/json'
@@ -204,20 +216,23 @@ def set_content_type(response, data, path):
return data
def clear_cache(path=None):
+ '''Clear website caches
+
+ :param path: (optional) for the given path'''
frappe.cache().delete_value("website_generator_routes")
delete_page_cache(path)
frappe.cache().delete_value("website_404")
if not path:
clear_sitemap()
frappe.clear_cache("Guest")
- frappe.cache().delete_value("portal_menu_items")
- frappe.cache().delete_value("home_page")
+ for key in ('portal_menu_items', 'home_page', 'website_route_rules',
+ 'doctypes_with_web_view'):
+ frappe.cache().delete_value(key)
for method in frappe.get_hooks("website_clear_cache"):
frappe.get_attr(method)(path)
def render_403(e, pathname):
- path = "message"
frappe.local.message = cstr(e.message)
frappe.local.message_title = _("Not Permitted")
frappe.local.response['context'] = dict(
@@ -225,7 +240,7 @@ def render_403(e, pathname):
primary_action = '/login',
primary_label = _('Login')
)
- return render_page(path), e.http_status_code
+ return render_page("message"), e.http_status_code
def get_doctype_from_path(path):
doctypes = frappe.db.sql_list("select name from tabDocType")
diff --git a/frappe/website/router.py b/frappe/website/router.py
index 5183ea2b37..f0bf58a9da 100644
--- a/frappe/website/router.py
+++ b/frappe/website/router.py
@@ -90,29 +90,30 @@ def get_all_page_context_from_doctypes():
def get_page_info_from_doctypes(path=None):
routes = {}
- for app in frappe.get_installed_apps():
- for doctype in frappe.get_hooks("website_generators", app_name = app):
- condition = ""
- values = []
- controller = get_controller(doctype)
-
- if controller.website.condition_field:
- condition ="where {0}=1".format(controller.website.condition_field)
-
- if path:
- condition += ' {0} `route`=%s limit 1'.format('and' if 'where' in condition else 'where')
- values.append(path)
-
- try:
- for r in frappe.db.sql("""select route, name, modified from `tab{0}`
- {1}""".format(doctype, condition), values=values, as_dict=True):
- routes[r.route] = {"doctype": doctype, "name": r.name, "modified": r.modified}
-
- # just want one path, return it!
- if path:
- return routes[r.route]
- except Exception, e:
- if e.args[0]!=1054: raise e
+ for doctype in get_doctypes_with_web_view():
+ condition = ""
+ values = []
+ controller = get_controller(doctype)
+ meta = frappe.get_meta(doctype)
+ condition_field = meta.is_published_field or controller.website.condition_field
+
+ if condition_field:
+ condition ="where {0}=1".format(condition_field)
+
+ if path:
+ condition += ' {0} `route`=%s limit 1'.format('and' if 'where' in condition else 'where')
+ values.append(path)
+
+ try:
+ for r in frappe.db.sql("""select route, name, modified from `tab{0}`
+ {1}""".format(doctype, condition), values=values, as_dict=True):
+ routes[r.route] = {"doctype": doctype, "name": r.name, "modified": r.modified}
+
+ # just want one path, return it!
+ if path:
+ return routes[r.route]
+ except Exception, e:
+ if e.args[0]!=1054: raise e
return routes
@@ -316,18 +317,13 @@ def load_properties(page_info):
if "" in page_info.source:
page_info.no_cache = 1
-def process_generators(func):
- for app in frappe.get_installed_apps():
- for doctype in frappe.get_hooks("website_generators", app_name = app):
- order_by = "name asc"
- condition_field = None
- controller = get_controller(doctype)
-
- if "condition_field" in controller.website:
- condition_field = controller.website['condition_field']
- if 'order_by' in controller.website:
- order_by = controller.website['order_by']
-
- val = func(doctype, condition_field, order_by)
- if val:
- return val
+def get_doctypes_with_web_view():
+ '''Return doctypes with Has Web View or set via hooks'''
+ def _get():
+ installed_apps = frappe.get_installed_apps()
+ doctypes = frappe.get_hooks("website_generators")
+ doctypes += [d.name for d in frappe.get_all('DocType', 'name, module',
+ dict(has_web_view=1)) if frappe.local.module_app[frappe.scrub(d.module)] in installed_apps]
+ return doctypes
+
+ return frappe.cache().get_value('doctypes_with_web_view', _get)
\ No newline at end of file
diff --git a/frappe/website/website_generator.py b/frappe/website/website_generator.py
index 6acc76b025..8887316732 100644
--- a/frappe/website/website_generator.py
+++ b/frappe/website/website_generator.py
@@ -43,7 +43,20 @@ class WebsiteGenerator(Document):
return self.scrubbed_title()
def scrubbed_title(self):
- return self.scrub(self.get(self.get_website_properties('page_title_field', 'title')))
+ return self.scrub(self.get(self.get_title_field()))
+
+ def get_title_field(self):
+ '''return title field from website properties or meta.title_field'''
+ title_field = self.get_website_properties('page_title_field')
+ if not title_field:
+ if self.meta.title_field:
+ title_field = self.meta.title_field
+ elif self.meta.has_field('title'):
+ title_field = 'title'
+ else:
+ title_field = 'name'
+
+ return title_field
def clear_cache(self):
clear_cache(self.route)
@@ -60,11 +73,19 @@ class WebsiteGenerator(Document):
def is_website_published(self):
"""Return true if published in website"""
- if self.get_website_properties('condition_field'):
- return self.get(self.get_website_properties('condition_field')) and True or False
+ if self.get_condition_field():
+ return self.get(self.get_condition_field()) and True or False
else:
return True
+ def get_condition_field(self):
+ condition_field = self.get_website_properties('condition_field')
+ if not condition_field:
+ if self.meta.is_published_field:
+ condition_field = self.meta.is_published_field
+
+ return condition_field
+
def get_page_info(self):
route = frappe._dict()
route.update({
@@ -79,7 +100,6 @@ class WebsiteGenerator(Document):
route.update(self.get_website_properties())
if not route.page_title:
- route.page_title = self.get(self.get_website_properties('page_title_field'), 'title') \
- or self.get('name')
+ route.page_title = self.get(self.get_title_field())
return route
diff --git a/frappe/www/list.py b/frappe/www/list.py
index 406b0c7d75..0d948f3ee4 100644
--- a/frappe/www/list.py
+++ b/frappe/www/list.py
@@ -45,10 +45,16 @@ def get(doctype, txt=None, limit_start=0, limit=20, **kwargs):
_get_list = list_context.get_list or get_list
- raw_result = _get_list(doctype=doctype, txt=txt, filters=filters,
+ kwargs = dict(doctype=doctype, txt=txt, filters=filters,
limit_start=limit_start, limit_page_length=limit_page_length + 1,
order_by = list_context.order_by or 'modified desc')
+ # allow guest if flag is set
+ if not list_context.get_list and (list_context.allow_guest or meta.allow_guest_to_view):
+ kwargs['ignore_permissions'] = True
+
+ raw_result = _get_list(**kwargs)
+
if not raw_result: return {"result": []}
show_more = len(raw_result) > limit_page_length
@@ -123,6 +129,10 @@ def get_list_context(context, doctype):
if out:
list_context = out
+ # get path from '/templates/' folder of the doctype
+ if not list_context.row_template:
+ list_context.row_template = frappe.get_meta(doctype).get_row_template()
+
# is web form, show the default web form filters
# which is only the owner
if frappe.form_dict.web_form_name: