* [enhance] add web view settings doctype * [enhance] add web view settings doctype * [fix] default for checks (?) * [fix] framework json * [fix] missing return * [fix] hooks for website_generatorsversion-14
@@ -1,5 +1,6 @@ | |||||
{ | { | ||||
"allow_copy": 0, | "allow_copy": 0, | ||||
"allow_guest_to_view": 0, | |||||
"allow_import": 0, | "allow_import": 0, | ||||
"allow_rename": 0, | "allow_rename": 0, | ||||
"autoname": "hash", | "autoname": "hash", | ||||
@@ -470,7 +471,7 @@ | |||||
"columns": 0, | "columns": 0, | ||||
"description": "For Links, enter the DocType as range.\nFor Select, enter list of Options, each on a new line.", | "description": "For Links, enter the DocType as range.\nFor Select, enter list of Options, each on a new line.", | ||||
"fieldname": "options", | "fieldname": "options", | ||||
"fieldtype": "Text", | |||||
"fieldtype": "Small Text", | |||||
"hidden": 0, | "hidden": 0, | ||||
"ignore_user_permissions": 0, | "ignore_user_permissions": 0, | ||||
"ignore_xss_filter": 0, | "ignore_xss_filter": 0, | ||||
@@ -1278,6 +1279,7 @@ | |||||
"unique": 0 | "unique": 0 | ||||
} | } | ||||
], | ], | ||||
"has_web_view": 0, | |||||
"hide_heading": 0, | "hide_heading": 0, | ||||
"hide_toolbar": 0, | "hide_toolbar": 0, | ||||
"idx": 1, | "idx": 1, | ||||
@@ -1288,7 +1290,7 @@ | |||||
"issingle": 0, | "issingle": 0, | ||||
"istable": 1, | "istable": 1, | ||||
"max_attachments": 0, | "max_attachments": 0, | ||||
"modified": "2017-02-22 21:43:00.771400", | |||||
"modified": "2017-03-03 16:18:13.523592", | |||||
"modified_by": "Administrator", | "modified_by": "Administrator", | ||||
"module": "Core", | "module": "Core", | ||||
"name": "DocField", | "name": "DocField", | ||||
@@ -1,5 +1,6 @@ | |||||
{ | { | ||||
"allow_copy": 0, | "allow_copy": 0, | ||||
"allow_guest_to_view": 0, | |||||
"allow_import": 0, | "allow_import": 0, | ||||
"allow_rename": 0, | "allow_rename": 0, | ||||
"autoname": "hash", | "autoname": "hash", | ||||
@@ -8,6 +9,7 @@ | |||||
"custom": 0, | "custom": 0, | ||||
"docstatus": 0, | "docstatus": 0, | ||||
"doctype": "DocType", | "doctype": "DocType", | ||||
"document_type": "Setup", | |||||
"editable_grid": 1, | "editable_grid": 1, | ||||
"fields": [ | "fields": [ | ||||
{ | { | ||||
@@ -21,6 +23,7 @@ | |||||
"ignore_user_permissions": 0, | "ignore_user_permissions": 0, | ||||
"ignore_xss_filter": 0, | "ignore_xss_filter": 0, | ||||
"in_filter": 0, | "in_filter": 0, | ||||
"in_global_search": 0, | |||||
"in_list_view": 0, | "in_list_view": 0, | ||||
"in_standard_filter": 0, | "in_standard_filter": 0, | ||||
"label": "Role and Level", | "label": "Role and Level", | ||||
@@ -48,6 +51,7 @@ | |||||
"ignore_user_permissions": 0, | "ignore_user_permissions": 0, | ||||
"ignore_xss_filter": 0, | "ignore_xss_filter": 0, | ||||
"in_filter": 0, | "in_filter": 0, | ||||
"in_global_search": 0, | |||||
"in_list_view": 1, | "in_list_view": 1, | ||||
"in_standard_filter": 0, | "in_standard_filter": 0, | ||||
"label": "Role", | "label": "Role", | ||||
@@ -81,6 +85,7 @@ | |||||
"ignore_user_permissions": 0, | "ignore_user_permissions": 0, | ||||
"ignore_xss_filter": 0, | "ignore_xss_filter": 0, | ||||
"in_filter": 0, | "in_filter": 0, | ||||
"in_global_search": 0, | |||||
"in_list_view": 0, | "in_list_view": 0, | ||||
"in_standard_filter": 0, | "in_standard_filter": 0, | ||||
"label": "Apply User Permissions", | "label": "Apply User Permissions", | ||||
@@ -109,6 +114,7 @@ | |||||
"ignore_user_permissions": 0, | "ignore_user_permissions": 0, | ||||
"ignore_xss_filter": 0, | "ignore_xss_filter": 0, | ||||
"in_filter": 0, | "in_filter": 0, | ||||
"in_global_search": 0, | |||||
"in_list_view": 0, | "in_list_view": 0, | ||||
"in_standard_filter": 0, | "in_standard_filter": 0, | ||||
"label": "If user is the owner", | "label": "If user is the owner", | ||||
@@ -137,6 +143,7 @@ | |||||
"ignore_user_permissions": 0, | "ignore_user_permissions": 0, | ||||
"ignore_xss_filter": 0, | "ignore_xss_filter": 0, | ||||
"in_filter": 0, | "in_filter": 0, | ||||
"in_global_search": 0, | |||||
"in_list_view": 0, | "in_list_view": 0, | ||||
"in_standard_filter": 0, | "in_standard_filter": 0, | ||||
"length": 0, | "length": 0, | ||||
@@ -164,6 +171,7 @@ | |||||
"ignore_user_permissions": 0, | "ignore_user_permissions": 0, | ||||
"ignore_xss_filter": 0, | "ignore_xss_filter": 0, | ||||
"in_filter": 0, | "in_filter": 0, | ||||
"in_global_search": 0, | |||||
"in_list_view": 1, | "in_list_view": 1, | ||||
"in_standard_filter": 0, | "in_standard_filter": 0, | ||||
"label": "Level", | "label": "Level", | ||||
@@ -197,6 +205,7 @@ | |||||
"ignore_user_permissions": 0, | "ignore_user_permissions": 0, | ||||
"ignore_xss_filter": 0, | "ignore_xss_filter": 0, | ||||
"in_filter": 0, | "in_filter": 0, | ||||
"in_global_search": 0, | |||||
"in_list_view": 0, | "in_list_view": 0, | ||||
"in_standard_filter": 0, | "in_standard_filter": 0, | ||||
"label": "User Permission DocTypes", | "label": "User Permission DocTypes", | ||||
@@ -224,6 +233,7 @@ | |||||
"ignore_user_permissions": 0, | "ignore_user_permissions": 0, | ||||
"ignore_xss_filter": 0, | "ignore_xss_filter": 0, | ||||
"in_filter": 0, | "in_filter": 0, | ||||
"in_global_search": 0, | |||||
"in_list_view": 0, | "in_list_view": 0, | ||||
"in_standard_filter": 0, | "in_standard_filter": 0, | ||||
"label": "Permissions", | "label": "Permissions", | ||||
@@ -252,6 +262,7 @@ | |||||
"ignore_user_permissions": 0, | "ignore_user_permissions": 0, | ||||
"ignore_xss_filter": 0, | "ignore_xss_filter": 0, | ||||
"in_filter": 0, | "in_filter": 0, | ||||
"in_global_search": 0, | |||||
"in_list_view": 1, | "in_list_view": 1, | ||||
"in_standard_filter": 0, | "in_standard_filter": 0, | ||||
"label": "Read", | "label": "Read", | ||||
@@ -284,6 +295,7 @@ | |||||
"ignore_user_permissions": 0, | "ignore_user_permissions": 0, | ||||
"ignore_xss_filter": 0, | "ignore_xss_filter": 0, | ||||
"in_filter": 0, | "in_filter": 0, | ||||
"in_global_search": 0, | |||||
"in_list_view": 1, | "in_list_view": 1, | ||||
"in_standard_filter": 0, | "in_standard_filter": 0, | ||||
"label": "Write", | "label": "Write", | ||||
@@ -316,6 +328,7 @@ | |||||
"ignore_user_permissions": 0, | "ignore_user_permissions": 0, | ||||
"ignore_xss_filter": 0, | "ignore_xss_filter": 0, | ||||
"in_filter": 0, | "in_filter": 0, | ||||
"in_global_search": 0, | |||||
"in_list_view": 1, | "in_list_view": 1, | ||||
"in_standard_filter": 0, | "in_standard_filter": 0, | ||||
"label": "Create", | "label": "Create", | ||||
@@ -348,6 +361,7 @@ | |||||
"ignore_user_permissions": 0, | "ignore_user_permissions": 0, | ||||
"ignore_xss_filter": 0, | "ignore_xss_filter": 0, | ||||
"in_filter": 0, | "in_filter": 0, | ||||
"in_global_search": 0, | |||||
"in_list_view": 1, | "in_list_view": 1, | ||||
"in_standard_filter": 0, | "in_standard_filter": 0, | ||||
"label": "Delete", | "label": "Delete", | ||||
@@ -375,6 +389,7 @@ | |||||
"ignore_user_permissions": 0, | "ignore_user_permissions": 0, | ||||
"ignore_xss_filter": 0, | "ignore_xss_filter": 0, | ||||
"in_filter": 0, | "in_filter": 0, | ||||
"in_global_search": 0, | |||||
"in_list_view": 0, | "in_list_view": 0, | ||||
"in_standard_filter": 0, | "in_standard_filter": 0, | ||||
"length": 0, | "length": 0, | ||||
@@ -401,6 +416,7 @@ | |||||
"ignore_user_permissions": 0, | "ignore_user_permissions": 0, | ||||
"ignore_xss_filter": 0, | "ignore_xss_filter": 0, | ||||
"in_filter": 0, | "in_filter": 0, | ||||
"in_global_search": 0, | |||||
"in_list_view": 1, | "in_list_view": 1, | ||||
"in_standard_filter": 0, | "in_standard_filter": 0, | ||||
"label": "Submit", | "label": "Submit", | ||||
@@ -432,6 +448,7 @@ | |||||
"ignore_user_permissions": 0, | "ignore_user_permissions": 0, | ||||
"ignore_xss_filter": 0, | "ignore_xss_filter": 0, | ||||
"in_filter": 0, | "in_filter": 0, | ||||
"in_global_search": 0, | |||||
"in_list_view": 1, | "in_list_view": 1, | ||||
"in_standard_filter": 0, | "in_standard_filter": 0, | ||||
"label": "Cancel", | "label": "Cancel", | ||||
@@ -463,6 +480,7 @@ | |||||
"ignore_user_permissions": 0, | "ignore_user_permissions": 0, | ||||
"ignore_xss_filter": 0, | "ignore_xss_filter": 0, | ||||
"in_filter": 0, | "in_filter": 0, | ||||
"in_global_search": 0, | |||||
"in_list_view": 0, | "in_list_view": 0, | ||||
"in_standard_filter": 0, | "in_standard_filter": 0, | ||||
"label": "Amend", | "label": "Amend", | ||||
@@ -494,6 +512,7 @@ | |||||
"ignore_user_permissions": 0, | "ignore_user_permissions": 0, | ||||
"ignore_xss_filter": 0, | "ignore_xss_filter": 0, | ||||
"in_filter": 0, | "in_filter": 0, | ||||
"in_global_search": 0, | |||||
"in_list_view": 0, | "in_list_view": 0, | ||||
"in_standard_filter": 0, | "in_standard_filter": 0, | ||||
"label": "Additional Permissions", | "label": "Additional Permissions", | ||||
@@ -522,6 +541,7 @@ | |||||
"ignore_user_permissions": 0, | "ignore_user_permissions": 0, | ||||
"ignore_xss_filter": 0, | "ignore_xss_filter": 0, | ||||
"in_filter": 0, | "in_filter": 0, | ||||
"in_global_search": 0, | |||||
"in_list_view": 0, | "in_list_view": 0, | ||||
"in_standard_filter": 0, | "in_standard_filter": 0, | ||||
"label": "Report", | "label": "Report", | ||||
@@ -552,6 +572,7 @@ | |||||
"ignore_user_permissions": 0, | "ignore_user_permissions": 0, | ||||
"ignore_xss_filter": 0, | "ignore_xss_filter": 0, | ||||
"in_filter": 0, | "in_filter": 0, | ||||
"in_global_search": 0, | |||||
"in_list_view": 0, | "in_list_view": 0, | ||||
"in_standard_filter": 0, | "in_standard_filter": 0, | ||||
"label": "Export", | "label": "Export", | ||||
@@ -579,6 +600,7 @@ | |||||
"ignore_user_permissions": 0, | "ignore_user_permissions": 0, | ||||
"ignore_xss_filter": 0, | "ignore_xss_filter": 0, | ||||
"in_filter": 0, | "in_filter": 0, | ||||
"in_global_search": 0, | |||||
"in_list_view": 0, | "in_list_view": 0, | ||||
"in_standard_filter": 0, | "in_standard_filter": 0, | ||||
"label": "Import", | "label": "Import", | ||||
@@ -607,6 +629,7 @@ | |||||
"ignore_user_permissions": 0, | "ignore_user_permissions": 0, | ||||
"ignore_xss_filter": 0, | "ignore_xss_filter": 0, | ||||
"in_filter": 0, | "in_filter": 0, | ||||
"in_global_search": 0, | |||||
"in_list_view": 0, | "in_list_view": 0, | ||||
"in_standard_filter": 0, | "in_standard_filter": 0, | ||||
"label": "Set User Permissions", | "label": "Set User Permissions", | ||||
@@ -634,6 +657,7 @@ | |||||
"ignore_user_permissions": 0, | "ignore_user_permissions": 0, | ||||
"ignore_xss_filter": 0, | "ignore_xss_filter": 0, | ||||
"in_filter": 0, | "in_filter": 0, | ||||
"in_global_search": 0, | |||||
"in_list_view": 0, | "in_list_view": 0, | ||||
"in_standard_filter": 0, | "in_standard_filter": 0, | ||||
"length": 0, | "length": 0, | ||||
@@ -661,6 +685,7 @@ | |||||
"ignore_user_permissions": 0, | "ignore_user_permissions": 0, | ||||
"ignore_xss_filter": 0, | "ignore_xss_filter": 0, | ||||
"in_filter": 0, | "in_filter": 0, | ||||
"in_global_search": 0, | |||||
"in_list_view": 0, | "in_list_view": 0, | ||||
"in_standard_filter": 0, | "in_standard_filter": 0, | ||||
"label": "Share", | "label": "Share", | ||||
@@ -690,6 +715,7 @@ | |||||
"ignore_user_permissions": 0, | "ignore_user_permissions": 0, | ||||
"ignore_xss_filter": 0, | "ignore_xss_filter": 0, | ||||
"in_filter": 0, | "in_filter": 0, | ||||
"in_global_search": 0, | |||||
"in_list_view": 0, | "in_list_view": 0, | ||||
"in_standard_filter": 0, | "in_standard_filter": 0, | ||||
"label": "Print", | "label": "Print", | ||||
@@ -718,6 +744,7 @@ | |||||
"ignore_user_permissions": 0, | "ignore_user_permissions": 0, | ||||
"ignore_xss_filter": 0, | "ignore_xss_filter": 0, | ||||
"in_filter": 0, | "in_filter": 0, | ||||
"in_global_search": 0, | |||||
"in_list_view": 0, | "in_list_view": 0, | ||||
"in_standard_filter": 0, | "in_standard_filter": 0, | ||||
"label": "Email", | "label": "Email", | ||||
@@ -735,6 +762,7 @@ | |||||
"unique": 0 | "unique": 0 | ||||
} | } | ||||
], | ], | ||||
"has_web_view": 0, | |||||
"hide_heading": 0, | "hide_heading": 0, | ||||
"hide_toolbar": 0, | "hide_toolbar": 0, | ||||
"idx": 1, | "idx": 1, | ||||
@@ -745,7 +773,7 @@ | |||||
"issingle": 0, | "issingle": 0, | ||||
"istable": 1, | "istable": 1, | ||||
"max_attachments": 0, | "max_attachments": 0, | ||||
"modified": "2017-01-11 04:21:44.249780", | |||||
"modified": "2017-03-03 16:18:18.890031", | |||||
"modified_by": "Administrator", | "modified_by": "Administrator", | ||||
"module": "Core", | "module": "Core", | ||||
"name": "DocPerm", | "name": "DocPerm", | ||||
@@ -754,6 +782,7 @@ | |||||
"quick_entry": 0, | "quick_entry": 0, | ||||
"read_only": 0, | "read_only": 0, | ||||
"read_only_onload": 0, | "read_only_onload": 0, | ||||
"show_name_in_global_search": 0, | |||||
"sort_order": "ASC", | "sort_order": "ASC", | ||||
"track_changes": 0, | "track_changes": 0, | ||||
"track_seen": 0 | "track_seen": 0 |
@@ -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 | // For license information, please see license.txt | ||||
frappe.ui.form.on('{doctype}', {{ | frappe.ui.form.on('{doctype}', {{ | ||||
@@ -1,5 +1,5 @@ | |||||
# -*- coding: utf-8 -*- | # -*- coding: utf-8 -*- | ||||
# Copyright (c) 2015, {app_publisher} and contributors | |||||
# Copyright (c) {year}, {app_publisher} and contributors | |||||
# For license information, please see license.txt | # For license information, please see license.txt | ||||
from __future__ import unicode_literals | from __future__ import unicode_literals | ||||
@@ -0,0 +1,7 @@ | |||||
{{% extends "templates/web.html" %}} | |||||
{{% block page_content %}} | |||||
<h1>{{{{ title }}}}</h1> | |||||
{{% endblock %}} | |||||
<!-- this is a sample default web page template --> |
@@ -0,0 +1,4 @@ | |||||
<div> | |||||
<a href={{{{ route }}}}>{{{{ title }}}}</a> | |||||
</div> | |||||
<!-- this is a sample default list template --> |
@@ -1,12 +1,10 @@ | |||||
# -*- coding: utf-8 -*- | # -*- coding: utf-8 -*- | ||||
# Copyright (c) 2015, {app_publisher} and Contributors | |||||
# Copyright (c) {year}, {app_publisher} and Contributors | |||||
# See license.txt | # See license.txt | ||||
from __future__ import unicode_literals | from __future__ import unicode_literals | ||||
import frappe | import frappe | ||||
import unittest | import unittest | ||||
# test_records = frappe.get_test_records('{doctype}') | |||||
class Test{classname}(unittest.TestCase): | class Test{classname}(unittest.TestCase): | ||||
pass | pass |
@@ -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.desk.notifications import delete_notification_count_for | ||||
from frappe.modules import make_boilerplate | from frappe.modules import make_boilerplate | ||||
from frappe.model.db_schema import validate_column_name | from frappe.model.db_schema import validate_column_name | ||||
import frappe.website.render | |||||
class InvalidFieldNameError(frappe.ValidationError): pass | class InvalidFieldNameError(frappe.ValidationError): pass | ||||
@@ -122,15 +123,13 @@ class DocType(Document): | |||||
def validate_website(self): | def validate_website(self): | ||||
"""Ensure that website generator has field 'route'""" | """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]: | 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): | def change_modified_of_parent(self): | ||||
"""Change the timestamp of parent DocType if the current one is a child to clear caches.""" | """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: | if not self.istable: | ||||
make_boilerplate("controller.js", self.as_dict()) | 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): | def make_amendable(self): | ||||
"""If is_submittable is set, add amended_from docfields.""" | """If is_submittable is set, add amended_from docfields.""" | ||||
if self.is_submittable: | if self.is_submittable: | ||||
@@ -497,6 +500,12 @@ def validate_fields(meta): | |||||
if df[0].fieldtype != 'Attach Image': | if df[0].fieldtype != 'Attach Image': | ||||
frappe.throw(_("Image field must be of type Attach Image"), InvalidFieldNameError) | 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): | def check_timeline_field(meta): | ||||
if not meta.timeline_field: | if not meta.timeline_field: | ||||
@@ -549,6 +558,7 @@ def validate_fields(meta): | |||||
check_search_fields(meta) | check_search_fields(meta) | ||||
check_title_field(meta) | check_title_field(meta) | ||||
check_timeline_field(meta) | check_timeline_field(meta) | ||||
check_is_published_field(meta) | |||||
check_sort_field(meta) | check_sort_field(meta) | ||||
def validate_permissions_for_doctype(doctype, for_remove=False): | def validate_permissions_for_doctype(doctype, for_remove=False): | ||||
@@ -141,7 +141,6 @@ CREATE TABLE `tabDocType` ( | |||||
`max_attachments` int(11) NOT NULL DEFAULT 0, | `max_attachments` int(11) NOT NULL DEFAULT 0, | ||||
`print_outline` varchar(255) DEFAULT NULL, | `print_outline` varchar(255) DEFAULT NULL, | ||||
`read_only_onload` int(1) NOT NULL DEFAULT 0, | `read_only_onload` int(1) NOT NULL DEFAULT 0, | ||||
`in_dialog` int(1) NOT NULL DEFAULT 0, | |||||
`document_type` varchar(255) DEFAULT NULL, | `document_type` varchar(255) DEFAULT NULL, | ||||
`icon` varchar(255) DEFAULT NULL, | `icon` varchar(255) DEFAULT NULL, | ||||
`tag_fields` varchar(255) DEFAULT NULL, | `tag_fields` varchar(255) DEFAULT NULL, | ||||
@@ -155,6 +154,10 @@ CREATE TABLE `tabDocType` ( | |||||
`custom` int(1) NOT NULL DEFAULT 0, | `custom` int(1) NOT NULL DEFAULT 0, | ||||
`beta` int(1) NOT NULL DEFAULT 0, | `beta` int(1) NOT NULL DEFAULT 0, | ||||
`image_view` 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`), | PRIMARY KEY (`name`), | ||||
KEY `parent` (`parent`) | KEY `parent` (`parent`) | ||||
) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8mb4 COLLATE=utf8mb4_unicode_ci; | ) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8mb4 COLLATE=utf8mb4_unicode_ci; | ||||
@@ -16,7 +16,7 @@ Example: | |||||
''' | ''' | ||||
from __future__ import unicode_literals | from __future__ import unicode_literals | ||||
import frappe, json | |||||
import frappe, json, os | |||||
from frappe.utils import cstr, cint | from frappe.utils import cstr, cint | ||||
from frappe.model import default_fields, no_value_fields, optional_fields | from frappe.model import default_fields, no_value_fields, optional_fields | ||||
from frappe.model.document import Document | from frappe.model.document import Document | ||||
@@ -352,6 +352,20 @@ class Meta(Document): | |||||
return data | 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 = [ | doctype_table_fields = [ | ||||
frappe._dict({"fieldname": "fields", "options": "DocField"}), | frappe._dict({"fieldname": "fields", "options": "DocField"}), | ||||
frappe._dict({"fieldname": "permissions", "options": "DocPerm"}) | frappe._dict({"fieldname": "permissions", "options": "DocPerm"}) | ||||
@@ -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) | if (not frappe.flags.in_import and getattr(frappe.get_conf(),'developer_mode', 0) | ||||
and is_standard): | and is_standard): | ||||
from frappe.modules.export_file import export_to_files | from frappe.modules.export_file import export_to_files | ||||
from frappe.modules import get_module_path | |||||
# json | # json | ||||
export_to_files(record_list=[[doc.doctype, doc.name]], record_module=module) | 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)) | scrub(doc.name), scrub(doc.name)) | ||||
return path | return path | ||||
@@ -209,6 +208,8 @@ def make_boilerplate(template, doc, opts=None): | |||||
template_name = template.replace("controller", scrub(doc.name)) | template_name = template.replace("controller", scrub(doc.name)) | ||||
target_file_path = os.path.join(target_path, template_name) | target_file_path = os.path.join(target_path, template_name) | ||||
if not doc: doc = {} | |||||
app_publisher = get_app_publisher(doc.module) | app_publisher = get_app_publisher(doc.module) | ||||
if not os.path.exists(target_file_path): | 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), | with open(os.path.join(get_module_path("core"), "doctype", scrub(doc.doctype), | ||||
"boilerplate", template), 'r') as source: | "boilerplate", template), 'r') as source: | ||||
target.write(frappe.utils.encode( | 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) | |||||
)) | )) |
@@ -6,9 +6,9 @@ frappe.patches.v7_1.rename_scheduler_log_to_error_log | |||||
frappe.patches.v6_1.rename_file_data | frappe.patches.v6_1.rename_file_data | ||||
frappe.patches.v7_0.re_route #2016-06-27 | frappe.patches.v7_0.re_route #2016-06-27 | ||||
frappe.patches.v7_2.remove_in_filter | 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') | execute:frappe.reload_doc('core', 'doctype', 'custom_docperm') | ||||
frappe.patches.v7_2.setup_custom_perms #2017-01-19 | frappe.patches.v7_2.setup_custom_perms #2017-01-19 | ||||
execute:frappe.reload_doc('core', 'doctype', 'role') | execute:frappe.reload_doc('core', 'doctype', 'role') | ||||
@@ -83,6 +83,9 @@ def build_context(context): | |||||
if ret: | if ret: | ||||
context.update(ret) | context.update(ret) | ||||
if not context.template: | |||||
context.template = context.doc.meta.get_web_template() | |||||
for prop in ("no_cache", "no_sitemap"): | for prop in ("no_cache", "no_sitemap"): | ||||
if not prop in context: | if not prop in context: | ||||
context[prop] = getattr(context.doc, prop, False) | context[prop] = getattr(context.doc, prop, False) | ||||
@@ -169,7 +169,7 @@ def resolve_path(path): | |||||
def resolve_from_map(path): | def resolve_from_map(path): | ||||
m = Map([Rule(r["from_route"], endpoint=r["to_route"], defaults=r.get("defaults")) | 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) | urls = m.bind_to_environ(frappe.local.request.environ) | ||||
try: | try: | ||||
endpoint, args = urls.match("/" + path) | endpoint, args = urls.match("/" + path) | ||||
@@ -184,6 +184,18 @@ def resolve_from_map(path): | |||||
return 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): | def set_content_type(response, data, path): | ||||
if isinstance(data, dict): | if isinstance(data, dict): | ||||
response.mimetype = 'application/json' | response.mimetype = 'application/json' | ||||
@@ -204,20 +216,23 @@ def set_content_type(response, data, path): | |||||
return data | return data | ||||
def clear_cache(path=None): | def clear_cache(path=None): | ||||
'''Clear website caches | |||||
:param path: (optional) for the given path''' | |||||
frappe.cache().delete_value("website_generator_routes") | frappe.cache().delete_value("website_generator_routes") | ||||
delete_page_cache(path) | delete_page_cache(path) | ||||
frappe.cache().delete_value("website_404") | frappe.cache().delete_value("website_404") | ||||
if not path: | if not path: | ||||
clear_sitemap() | clear_sitemap() | ||||
frappe.clear_cache("Guest") | 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"): | for method in frappe.get_hooks("website_clear_cache"): | ||||
frappe.get_attr(method)(path) | frappe.get_attr(method)(path) | ||||
def render_403(e, pathname): | def render_403(e, pathname): | ||||
path = "message" | |||||
frappe.local.message = cstr(e.message) | frappe.local.message = cstr(e.message) | ||||
frappe.local.message_title = _("Not Permitted") | frappe.local.message_title = _("Not Permitted") | ||||
frappe.local.response['context'] = dict( | frappe.local.response['context'] = dict( | ||||
@@ -225,7 +240,7 @@ def render_403(e, pathname): | |||||
primary_action = '/login', | primary_action = '/login', | ||||
primary_label = _('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): | def get_doctype_from_path(path): | ||||
doctypes = frappe.db.sql_list("select name from tabDocType") | doctypes = frappe.db.sql_list("select name from tabDocType") | ||||
@@ -90,29 +90,30 @@ def get_all_page_context_from_doctypes(): | |||||
def get_page_info_from_doctypes(path=None): | def get_page_info_from_doctypes(path=None): | ||||
routes = {} | 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 | return routes | ||||
@@ -316,18 +317,13 @@ def load_properties(page_info): | |||||
if "<!-- no-sitemap -->" in page_info.source: | if "<!-- no-sitemap -->" in page_info.source: | ||||
page_info.no_cache = 1 | 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) |
@@ -43,7 +43,20 @@ class WebsiteGenerator(Document): | |||||
return self.scrubbed_title() | return self.scrubbed_title() | ||||
def scrubbed_title(self): | 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): | def clear_cache(self): | ||||
clear_cache(self.route) | clear_cache(self.route) | ||||
@@ -60,11 +73,19 @@ class WebsiteGenerator(Document): | |||||
def is_website_published(self): | def is_website_published(self): | ||||
"""Return true if published in website""" | """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: | else: | ||||
return True | 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): | def get_page_info(self): | ||||
route = frappe._dict() | route = frappe._dict() | ||||
route.update({ | route.update({ | ||||
@@ -79,7 +100,6 @@ class WebsiteGenerator(Document): | |||||
route.update(self.get_website_properties()) | route.update(self.get_website_properties()) | ||||
if not route.page_title: | 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 | return route |
@@ -45,10 +45,16 @@ def get(doctype, txt=None, limit_start=0, limit=20, **kwargs): | |||||
_get_list = list_context.get_list or get_list | _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, | limit_start=limit_start, limit_page_length=limit_page_length + 1, | ||||
order_by = list_context.order_by or 'modified desc') | 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": []} | if not raw_result: return {"result": []} | ||||
show_more = len(raw_result) > limit_page_length | show_more = len(raw_result) > limit_page_length | ||||
@@ -123,6 +129,10 @@ def get_list_context(context, doctype): | |||||
if out: | if out: | ||||
list_context = 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 | # is web form, show the default web form filters | ||||
# which is only the owner | # which is only the owner | ||||
if frappe.form_dict.web_form_name: | if frappe.form_dict.web_form_name: | ||||