diff --git a/frappe/change_log/current/portal_roles.md b/frappe/change_log/current/portal_roles.md new file mode 100644 index 0000000000..4255c41266 --- /dev/null +++ b/frappe/change_log/current/portal_roles.md @@ -0,0 +1,2 @@ +- Portal Users (Customers, Supplier, Students) can now have roles +- Sidebar in portal view will be rendered as per roles and can be configured from Portal Settings \ No newline at end of file diff --git a/frappe/core/doctype/doctype/doctype.py b/frappe/core/doctype/doctype/doctype.py index cccd603fcf..80e40f7ac4 100644 --- a/frappe/core/doctype/doctype/doctype.py +++ b/frappe/core/doctype/doctype/doctype.py @@ -593,8 +593,7 @@ def make_module_and_roles(doc, perm_fieldname="permissions"): for role in list(set(roles)): if not frappe.db.exists("Role", role): - r = frappe.get_doc({"doctype": "Role", "role_name": role}) - r.role_name = role + r = frappe.get_doc(dict(doctype= "Role", role_name=role, desk_access=1)) r.flags.ignore_mandatory = r.flags.ignore_permissions = True r.insert() except frappe.DoesNotExistError, e: diff --git a/frappe/core/doctype/role/role.json b/frappe/core/doctype/role/role.json index 7567c24500..9e056dfe2a 100644 --- a/frappe/core/doctype/role/role.json +++ b/frappe/core/doctype/role/role.json @@ -14,13 +14,14 @@ "allow_on_submit": 0, "bold": 0, "collapsible": 0, + "columns": 0, "fieldname": "role_name", "fieldtype": "Data", "hidden": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, - "in_list_view": 1, + "in_list_view": 0, "label": "Role Name", "length": 0, "no_copy": 0, @@ -40,6 +41,7 @@ "allow_on_submit": 0, "bold": 0, "collapsible": 0, + "columns": 0, "description": "If disabled, this role will be removed from all users.", "fieldname": "disabled", "fieldtype": "Check", @@ -61,6 +63,33 @@ "search_index": 0, "set_only_once": 0, "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "default": "1", + "fieldname": "desk_access", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 1, + "label": "Desk Access", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 } ], "hide_heading": 0, @@ -74,7 +103,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2016-07-25 05:24:24.406260", + "modified": "2016-09-23 05:38:14.727541", "modified_by": "Administrator", "module": "Core", "name": "Role", diff --git a/frappe/core/doctype/role/test_records.json b/frappe/core/doctype/role/test_records.json index 9008a92c39..49442e6e42 100644 --- a/frappe/core/doctype/role/test_records.json +++ b/frappe/core/doctype/role/test_records.json @@ -1,14 +1,22 @@ [ { - "doctype": "Role", - "role_name": "_Test Role" - }, + "doctype": "Role", + "role_name": "_Test Role", + "desk_access": 1 + }, { - "doctype": "Role", - "role_name": "_Test Role 2" - }, + "doctype": "Role", + "role_name": "_Test Role 2", + "desk_access": 1 + }, { - "doctype": "Role", - "role_name": "_Test Role 3" + "doctype": "Role", + "role_name": "_Test Role 3", + "desk_access": 1 + }, + { + "doctype": "Role", + "role_name": "_Test Role 4", + "desk_access": 0 } ] \ No newline at end of file diff --git a/frappe/core/doctype/user/test_user.py b/frappe/core/doctype/user/test_user.py index 1bdc419c8c..38c58268ef 100644 --- a/frappe/core/doctype/user/test_user.py +++ b/frappe/core/doctype/user/test_user.py @@ -16,6 +16,29 @@ from frappe.core.doctype.user.user import MaxUsersReachedError test_records = frappe.get_test_records('User') class TestUser(unittest.TestCase): + def test_user_type(self): + new_user = frappe.get_doc(dict(doctype='User', email='test-for-type@example.com', + first_name='Tester')).insert() + self.assertEquals(new_user.user_type, 'Website User') + + # role with desk access + new_user.add_roles('_Test Role 2') + new_user.save() + self.assertEquals(new_user.user_type, 'System User') + + # clear role + new_user.user_roles = [] + new_user.save() + self.assertEquals(new_user.user_type, 'Website User') + + # role without desk access + new_user.add_roles('_Test Role 4') + new_user.save() + self.assertEquals(new_user.user_type, 'Website User') + + frappe.delete_doc('User', new_user.name) + + def test_delete(self): frappe.get_doc("User", "test@example.com").add_roles("_Test Role 2") self.assertRaises(frappe.LinkExistsError, delete_doc, "Role", "_Test Role 2") diff --git a/frappe/core/doctype/user/user.py b/frappe/core/doctype/user/user.py index 539cd94d41..e000dff613 100644 --- a/frappe/core/doctype/user/user.py +++ b/frappe/core/doctype/user/user.py @@ -38,6 +38,9 @@ class User(Document): [m.module_name for m in frappe.db.get_all('Desktop Icon', fields=['module_name'], filters={'standard': 1}, order_by="module_name")]) + def after_insert(self): + self.set_default_roles() + def validate(self): self.check_demo() @@ -93,6 +96,33 @@ class User(Document): if not cint(self.enabled) and getattr(frappe.local, "login_manager", None): frappe.local.login_manager.logout(user=self.name) + def set_default_roles(self): + """Set a default role if specified by rules (`default_role`) in hooks or Portal Settings + + Hooks for default roles can be set as: + + default_roles = [ + {'role': 'Customer', 'doctype':'Contact', 'email_field': 'email_id', + 'filters': {'ifnull(customer, "")': ('!=', '')}} + ] + + """ + role_found = False + for rule in frappe.get_hooks('default_roles'): + filters = {rule.get('email_field'): self.email} + if rule.get('filters'): + filters.update(rule.get('filters')) + + match = frappe.get_all(rule.get('doctype'), filters=filters, limit=1) + if match: + role_found = True + self.add_roles(rule.get('role')) + + if not role_found: + default_role = frappe.db.get_single_value('Portal Settings', 'default_role') + if default_role: + self.add_roles(default_role) + def add_system_manager_role(self): # if adding system manager, do nothing if not cint(self.enabled) or ("System Manager" in [user_role.role for user_role in @@ -128,11 +158,23 @@ class User(Document): frappe.msgprint(_("New password emailed")) def set_system_user(self): - if self.user_roles or self.name == 'Administrator': + '''Set as System User if any of the given roles has desk_access''' + if self.has_desk_access() or self.name == 'Administrator': self.user_type = 'System User' else: self.user_type = 'Website User' + def has_desk_access(self): + '''Return true if any of the set roles has desk access''' + if not self.user_roles: + return False + + return len(frappe.db.sql("""select name + from `tabRole` where desk_access=1 + and name in ({0}) limit 1""".format(', '.join(['%s'] * len(self.user_roles))), + [d.role for d in self.user_roles])) + + def share_with_self(self): if self.user_type=="System User": frappe.share.add(self.doctype, self.name, self.name, share=1, diff --git a/frappe/docs/assets/img/portals/portal-settings.png b/frappe/docs/assets/img/portals/portal-settings.png new file mode 100644 index 0000000000..3d88c254a8 Binary files /dev/null and b/frappe/docs/assets/img/portals/portal-settings.png differ diff --git a/frappe/docs/assets/img/portals/sample-web-form.png b/frappe/docs/assets/img/portals/sample-web-form.png new file mode 100644 index 0000000000..ebf4574fc9 Binary files /dev/null and b/frappe/docs/assets/img/portals/sample-web-form.png differ diff --git a/frappe/docs/assets/query-report-out.png b/frappe/docs/assets/img/query-report-out.png similarity index 100% rename from frappe/docs/assets/query-report-out.png rename to frappe/docs/assets/img/query-report-out.png diff --git a/frappe/docs/assets/query-report.png b/frappe/docs/assets/img/query-report.png similarity index 100% rename from frappe/docs/assets/query-report.png rename to frappe/docs/assets/img/query-report.png diff --git a/frappe/docs/user/en/guides/portal-development/building.md b/frappe/docs/user/en/guides/portal-development/building.md deleted file mode 100755 index 1e7ca23c9a..0000000000 --- a/frappe/docs/user/en/guides/portal-development/building.md +++ /dev/null @@ -1,15 +0,0 @@ -# Building the site - -To make the pages to be served on the web, they must first be synced with the database. This is done by running: - - bench --site sitename sync-www - -To re-build the site - - bench --site sitename --force sync-www - -Clearing the website cache - - bench --site sitename clear-website-cache - -{next} diff --git a/frappe/docs/user/en/guides/portal-development/contents.md b/frappe/docs/user/en/guides/portal-development/contents.md index c2ebaf5551..fc2fa6936c 100755 --- a/frappe/docs/user/en/guides/portal-development/contents.md +++ b/frappe/docs/user/en/guides/portal-development/contents.md @@ -7,11 +7,23 @@ You can also make Previous and Next buttons by adding `previous` or `next` in `{ ### Showing contents # This is a title - + Hello paragraph - + ### Contents: - + {index} {next} + +### Ordering + +You can defining the ordering of pages in index by defining the index.txt file in your folder. The index.txt file must have the names (without extensions) of the pages in that folder indicating the order. + +For example for this folder the `index.txt` looks like: + + adding-pages + ordering + contents + context + building diff --git a/frappe/docs/user/en/guides/portal-development/context.md b/frappe/docs/user/en/guides/portal-development/context.md index 5c72a1835b..d0fdc3cf63 100755 --- a/frappe/docs/user/en/guides/portal-development/context.md +++ b/frappe/docs/user/en/guides/portal-development/context.md @@ -1,8 +1,26 @@ -# Adding to context +# Dynamic Pages -You can add more data for the pages by adding a `.py` file with the same filename (e.g. `index.py` for `index.md`) with a `get_context` method. +You can render pages dynamically using Jinja templating language. To query data, you can update that `context` object that you pass to the template. +This can be done by adding a `.py` file with the same filename (e.g. `index.py` for `index.md`) with a `get_context` method. + +### Example + +If you want to show a page to see users, make a `users.html` and `users.py` file in the `www/` folder. + +In `users.py`: + + import frappe def get_context(context): - context.data = frappe.db.sql("some query") + context.users = frappe.db.sql("select first_name, last_name from `tabUser`") + +In `users.html`: + +

List of Users

+
    + {% for user in users %} +
  1. {{ user.first_name }} {{ user.last_name or "" }}
  2. + {% endfor %} +
{next} diff --git a/frappe/docs/user/en/guides/portal-development/index.md b/frappe/docs/user/en/guides/portal-development/index.md index 348e7cf9e5..a9aaab4312 100755 --- a/frappe/docs/user/en/guides/portal-development/index.md +++ b/frappe/docs/user/en/guides/portal-development/index.md @@ -1,7 +1,17 @@ # Making Portals +Frappe has powerful tools to build portals where pages can be dynamically generated using templates (Jinja) and users can be shown records after login + +#### Adding Pages + You can make your website by adding pages to the `/www` folder of your website. The urls of your site will match the path of your pages within the `/www` folder. Pages must be `.html` or `.md` (Markdown) files. Basic HTML template is provided in frappe in `frappe/templates/base_template.html` +#### Views after Login + +After logging in, the user sees a "My Account" page `/me` where user can access certain documents that are shown via a menu + +The user can view records based on permissions and also add / edit them with **Web Forms** + {index} diff --git a/frappe/docs/user/en/guides/portal-development/index.txt b/frappe/docs/user/en/guides/portal-development/index.txt index 875325806e..bf00b5d541 100755 --- a/frappe/docs/user/en/guides/portal-development/index.txt +++ b/frappe/docs/user/en/guides/portal-development/index.txt @@ -1,6 +1,6 @@ adding-pages -ordering -contents context -building generators +contents +web-forms +portal-roles diff --git a/frappe/docs/user/en/guides/portal-development/portal-roles.md b/frappe/docs/user/en/guides/portal-development/portal-roles.md new file mode 100644 index 0000000000..9c23d006c4 --- /dev/null +++ b/frappe/docs/user/en/guides/portal-development/portal-roles.md @@ -0,0 +1,25 @@ +# Portal Roles + +Version: 7.1+ + +Roles can be assigned to Website Users and they will see menu based on their role + +1. A default role can be set in **Portal Settings** +1. Each Portal Menu Item can have a role associated with it. If that role is set, then only those users having that role can see that menu item +1. Rules can be set for default roles that will be set on default users on hooks + + + +#### Rules for Default Role + +For example if the email id matches with a contact id, then set role Customer or Supplier: + + default_roles = [ + {'role': 'Customer', 'doctype':'Contact', 'email_field': 'email_id', + 'filters': {'ifnull(customer, "")': ('!=', '')}}, + {'role': 'Supplier', 'doctype':'Contact', 'email_field': 'email_id', + 'filters': {'ifnull(supplier, "")': ('!=', '')}}, + {'role': 'Student', 'doctype':'Student', 'email_field': 'student_email_id'} + ] + + diff --git a/frappe/docs/user/en/guides/portal-development/web-forms.md b/frappe/docs/user/en/guides/portal-development/web-forms.md new file mode 100644 index 0000000000..92e9c603ac --- /dev/null +++ b/frappe/docs/user/en/guides/portal-development/web-forms.md @@ -0,0 +1,11 @@ +# Customizing Web Forms + +Web Forms are a powerful way to add forms to your website. Web forms are powerful and scriptable and from Version 7.1+ they also include tables, paging and other utilties + + + +### Standard Web Forms + +If you check on the "Is Standard" checkbox, a new folder will be created in the `module` of the Web Form for that web form. In this folder, you will see a `.py` and `.js` file that you can customize the web form with. + +{next} \ No newline at end of file diff --git a/frappe/docs/user/en/guides/reports-and-printing/how-to-make-query-report.md b/frappe/docs/user/en/guides/reports-and-printing/how-to-make-query-report.md index 92ea7d4b2e..a9421387c7 100755 --- a/frappe/docs/user/en/guides/reports-and-printing/how-to-make-query-report.md +++ b/frappe/docs/user/en/guides/reports-and-printing/how-to-make-query-report.md @@ -6,7 +6,7 @@ To create a new Query Report: ### 1. Create a new Report -![Query Report](/assets/frappe_io/images/how-to/query-report.png) + 1. Set type as "Query Report" 1. Set the reference DocType - Users that have access to the reference DocType will have access to the report @@ -35,7 +35,7 @@ You can define complex queries such as: ### 3. Check the Report -![Query Report](/assets/frappe_io/images/how-to/query-report-out.png) + ### 4. Advanced (adding filters) diff --git a/frappe/model/db_query.py b/frappe/model/db_query.py index 984e4657b2..c8c924d308 100644 --- a/frappe/model/db_query.py +++ b/frappe/model/db_query.py @@ -267,8 +267,11 @@ class DatabaseQuery(object): if not tname in self.tables: self.append_table(tname) - column_name = '{tname}.{fname}'.format(tname=tname, - fname=f.fieldname) + if 'ifnull(' in f.fieldname: + column_name = f.fieldname + else: + column_name = '{tname}.{fname}'.format(tname=tname, + fname=f.fieldname) can_be_null = True @@ -317,8 +320,10 @@ class DatabaseQuery(object): if isinstance(value, basestring): value = '"{0}"'.format(frappe.db.escape(value, percent=False)) - if (self.ignore_ifnull or not can_be_null - or (f.value and f.operator in ('=', 'like')) or 'ifnull(' in column_name.lower()): + if (self.ignore_ifnull + or not can_be_null + or (f.value and f.operator in ('=', 'like')) + or 'ifnull(' in column_name.lower()): condition = '{column_name} {operator} {value}'.format( column_name=column_name, operator=f.operator, value=value) diff --git a/frappe/public/css/docs.css b/frappe/public/css/docs.css index 257506c5af..dcd26f54dd 100644 --- a/frappe/public/css/docs.css +++ b/frappe/public/css/docs.css @@ -187,6 +187,14 @@ #navbar-breadcrumbs > li > a { padding: 6px 15px 10px 0px; } +@media (min-width: 991px) and (max-width: 1199px) { + #navbar-breadcrumbs > li > a { + max-width: 143px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } +} .toolbar-user-fullname { max-width: 200px; display: inline-block; diff --git a/frappe/sessions.py b/frappe/sessions.py index 3dc3983772..56033dece0 100644 --- a/frappe/sessions.py +++ b/frappe/sessions.py @@ -31,7 +31,8 @@ def clear_cache(user=None): cache = frappe.cache() groups = ("bootinfo", "user_recent", "user_roles", "user_doc", "lang", - "defaults", "user_permissions", "roles", "home_page", "linked_with", "desktop_icons") + "defaults", "user_permissions", "roles", "home_page", "linked_with", + "desktop_icons", 'portal_menu_items') if user: for name in groups: diff --git a/frappe/website/context.py b/frappe/website/context.py index 09d82f7f91..43e31d3708 100644 --- a/frappe/website/context.py +++ b/frappe/website/context.py @@ -3,7 +3,6 @@ from __future__ import unicode_literals import frappe -import json from frappe.website.doctype.website_settings.website_settings import get_website_settings from frappe.website.router import get_page_context @@ -83,7 +82,7 @@ def build_context(context): elif context.controller: # controller based context update_controller_context(context, context.controller) - + # controller context extensions context_controller_hooks = frappe.get_hooks("extend_website_page_controller_context") or {} for controller, extension in context_controller_hooks.items(): @@ -96,6 +95,9 @@ def build_context(context): add_metatags(context) + if frappe.session.user == 'Guest': + context.show_sidebar = 0 + if context.show_sidebar: add_sidebar_data(context) @@ -111,13 +113,17 @@ def add_sidebar_data(context): import frappe.www.list if not context.sidebar_items: - sidebar_items = json.loads(frappe.cache().get_value('portal_menu_items') or '[]') - - if not sidebar_items: + sidebar_items = frappe.cache().hget('portal_menu_items', frappe.session.user) + if sidebar_items == None: + roles = frappe.get_roles() sidebar_items = frappe.get_all('Portal Menu Item', - fields=['title', 'route', 'reference_doctype', 'show_always'], + fields=['title', 'route', 'reference_doctype', 'role'], filters={'enabled': 1, 'parent': 'Portal Settings'}, order_by='idx asc') - frappe.cache().set_value('portal_menu_items', json.dumps(sidebar_items)) + + # filter sidebar items by role + sidebar_items = filter(lambda i: i.role==None or i.role in roles, sidebar_items) + + frappe.cache().hset('portal_menu_items', frappe.session.user, sidebar_items) context.sidebar_items = sidebar_items diff --git a/frappe/website/doctype/portal_menu_item/portal_menu_item.json b/frappe/website/doctype/portal_menu_item/portal_menu_item.json index e51dd2e2ee..b8aabdda57 100644 --- a/frappe/website/doctype/portal_menu_item/portal_menu_item.json +++ b/frappe/website/doctype/portal_menu_item/portal_menu_item.json @@ -14,7 +14,7 @@ "allow_on_submit": 0, "bold": 0, "collapsible": 0, - "columns": 0, + "columns": 2, "fieldname": "title", "fieldtype": "Data", "hidden": 0, @@ -40,7 +40,7 @@ "allow_on_submit": 0, "bold": 0, "collapsible": 0, - "columns": 0, + "columns": 1, "fieldname": "enabled", "fieldtype": "Check", "hidden": 0, @@ -66,7 +66,7 @@ "allow_on_submit": 0, "bold": 0, "collapsible": 0, - "columns": 0, + "columns": 3, "fieldname": "route", "fieldtype": "Data", "hidden": 0, @@ -92,7 +92,7 @@ "allow_on_submit": 0, "bold": 0, "collapsible": 0, - "columns": 0, + "columns": 2, "description": "", "fieldname": "reference_doctype", "fieldtype": "Link", @@ -120,22 +120,23 @@ "allow_on_submit": 0, "bold": 0, "collapsible": 0, - "columns": 0, - "fieldname": "target", - "fieldtype": "Data", + "columns": 2, + "fieldname": "role", + "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, - "in_list_view": 0, - "label": "Target", + "in_list_view": 1, + "label": "Role", "length": 0, "no_copy": 0, + "options": "Role", "permlevel": 0, "precision": "", "print_hide": 0, "print_hide_if_no_value": 0, - "read_only": 1, + "read_only": 0, "report_hide": 0, "reqd": 0, "search_index": 0, @@ -147,21 +148,21 @@ "bold": 0, "collapsible": 0, "columns": 0, - "fieldname": "show_always", - "fieldtype": "Check", + "fieldname": "target", + "fieldtype": "Data", "hidden": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "label": "Show Always", + "label": "Target", "length": 0, "no_copy": 0, "permlevel": 0, "precision": "", "print_hide": 0, "print_hide_if_no_value": 0, - "read_only": 0, + "read_only": 1, "report_hide": 0, "reqd": 0, "search_index": 0, @@ -179,7 +180,7 @@ "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2016-09-13 13:08:58.890253", + "modified": "2016-09-23 05:42:17.928917", "modified_by": "Administrator", "module": "Website", "name": "Portal Menu Item", diff --git a/frappe/website/doctype/portal_settings/portal_settings.json b/frappe/website/doctype/portal_settings/portal_settings.json index 38d8597f1d..be1f195f9f 100644 --- a/frappe/website/doctype/portal_settings/portal_settings.json +++ b/frappe/website/doctype/portal_settings/portal_settings.json @@ -2,16 +2,46 @@ "allow_copy": 0, "allow_import": 0, "allow_rename": 0, + "beta": 0, "creation": "2016-03-30 01:40:20.001775", "custom": 0, "docstatus": 0, "doctype": "DocType", "document_type": "", + "editable_grid": 0, "fields": [ { "allow_on_submit": 0, "bold": 0, "collapsible": 0, + "columns": 0, + "fieldname": "default_role", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Default Role at Time of Signup", + "length": 0, + "no_copy": 0, + "options": "Role", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 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": "menu", "fieldtype": "Table", "hidden": 0, @@ -38,13 +68,14 @@ "hide_heading": 0, "hide_toolbar": 0, "idx": 0, + "image_view": 0, "in_create": 0, "in_dialog": 0, "is_submittable": 0, "issingle": 1, "istable": 0, "max_attachments": 0, - "modified": "2016-03-30 01:40:20.001775", + "modified": "2016-09-23 06:34:18.718351", "modified_by": "Administrator", "module": "Website", "name": "Portal Settings", @@ -72,6 +103,7 @@ "write": 1 } ], + "quick_entry": 0, "read_only": 0, "read_only_onload": 0, "sort_field": "modified", diff --git a/frappe/website/doctype/portal_settings/portal_settings.py b/frappe/website/doctype/portal_settings/portal_settings.py index 465bcd2db1..4e328ad197 100644 --- a/frappe/website/doctype/portal_settings/portal_settings.py +++ b/frappe/website/doctype/portal_settings/portal_settings.py @@ -8,8 +8,13 @@ from frappe.model.document import Document class PortalSettings(Document): def add_item(self, item): - '''insert new portal menu item if route is not set''' - if not item.get('route') in [d.route for d in self.get('menu', [])]: + '''insert new portal menu item if route is not set, or role is different''' + exists = [d for d in self.get('menu', []) if d.get('route')==item.get('route')] + if exists and item.get('role'): + if exists[0].role != item.get('role'): + exists[0].role = item.get('role') + return True + else: item['enabled'] = 1 self.append('menu', item) return True @@ -29,3 +34,18 @@ class PortalSettings(Document): if dirty: self.save() + def on_update(self): + self.clear_cache() + + def clear_cache(self): + # make js and css + # clear web cache (for menus!) + from frappe.sessions import clear_cache + clear_cache('Guest') + + from frappe.website.render import clear_cache + clear_cache() + + # clears role based home pages + frappe.clear_cache() + diff --git a/frappe/website/doctype/web_form/web_form.json b/frappe/website/doctype/web_form/web_form.json index 4ae04d384b..b1229d90ba 100644 --- a/frappe/website/doctype/web_form/web_form.json +++ b/frappe/website/doctype/web_form/web_form.json @@ -499,6 +499,33 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "default": "1", + "fieldname": "show_sidebar", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Show Sidebar", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, { "allow_on_submit": 0, "bold": 0, @@ -618,7 +645,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2016-09-20 07:06:10.839930", + "modified": "2016-09-23 06:48:31.461495", "modified_by": "Administrator", "module": "Website", "name": "Web Form", diff --git a/frappe/website/doctype/web_form/web_form.py b/frappe/website/doctype/web_form/web_form.py index 56505a0c15..72bfeb40a3 100644 --- a/frappe/website/doctype/web_form/web_form.py +++ b/frappe/website/doctype/web_form/web_form.py @@ -93,7 +93,6 @@ def get_context(context): """) def get_context(self, context): - context.show_sidebar=True from frappe.www.list import get_context as get_list_context frappe.form_dict.is_web_form = 1 diff --git a/frappe/website/doctype/web_page/web_page.py b/frappe/website/doctype/web_page/web_page.py index 753b83ee22..4b26facf63 100644 --- a/frappe/website/doctype/web_page/web_page.py +++ b/frappe/website/doctype/web_page/web_page.py @@ -67,7 +67,7 @@ class WebPage(WebsiteGenerator): def set_breadcrumbs(self, context): """Build breadcrumbs template (deprecated)""" if not "no_breadcrumbs" in context: - if "" in context.main_section: + if "" in context.main_section or '': context.no_breadcrumbs = 1 def set_title_and_header(self, context):