* [enhance] added roles for portal users #2091 * [fix] test * [fix] make default roles have desk accessversion-14
@@ -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 |
@@ -593,8 +593,7 @@ def make_module_and_roles(doc, perm_fieldname="permissions"): | |||||
for role in list(set(roles)): | for role in list(set(roles)): | ||||
if not frappe.db.exists("Role", role): | 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.flags.ignore_mandatory = r.flags.ignore_permissions = True | ||||
r.insert() | r.insert() | ||||
except frappe.DoesNotExistError, e: | except frappe.DoesNotExistError, e: | ||||
@@ -14,13 +14,14 @@ | |||||
"allow_on_submit": 0, | "allow_on_submit": 0, | ||||
"bold": 0, | "bold": 0, | ||||
"collapsible": 0, | "collapsible": 0, | ||||
"columns": 0, | |||||
"fieldname": "role_name", | "fieldname": "role_name", | ||||
"fieldtype": "Data", | "fieldtype": "Data", | ||||
"hidden": 0, | "hidden": 0, | ||||
"ignore_user_permissions": 0, | "ignore_user_permissions": 0, | ||||
"ignore_xss_filter": 0, | "ignore_xss_filter": 0, | ||||
"in_filter": 0, | "in_filter": 0, | ||||
"in_list_view": 1, | |||||
"in_list_view": 0, | |||||
"label": "Role Name", | "label": "Role Name", | ||||
"length": 0, | "length": 0, | ||||
"no_copy": 0, | "no_copy": 0, | ||||
@@ -40,6 +41,7 @@ | |||||
"allow_on_submit": 0, | "allow_on_submit": 0, | ||||
"bold": 0, | "bold": 0, | ||||
"collapsible": 0, | "collapsible": 0, | ||||
"columns": 0, | |||||
"description": "If disabled, this role will be removed from all users.", | "description": "If disabled, this role will be removed from all users.", | ||||
"fieldname": "disabled", | "fieldname": "disabled", | ||||
"fieldtype": "Check", | "fieldtype": "Check", | ||||
@@ -61,6 +63,33 @@ | |||||
"search_index": 0, | "search_index": 0, | ||||
"set_only_once": 0, | "set_only_once": 0, | ||||
"unique": 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, | "hide_heading": 0, | ||||
@@ -74,7 +103,7 @@ | |||||
"issingle": 0, | "issingle": 0, | ||||
"istable": 0, | "istable": 0, | ||||
"max_attachments": 0, | "max_attachments": 0, | ||||
"modified": "2016-07-25 05:24:24.406260", | |||||
"modified": "2016-09-23 05:38:14.727541", | |||||
"modified_by": "Administrator", | "modified_by": "Administrator", | ||||
"module": "Core", | "module": "Core", | ||||
"name": "Role", | "name": "Role", | ||||
@@ -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 | |||||
} | } | ||||
] | ] |
@@ -16,6 +16,29 @@ from frappe.core.doctype.user.user import MaxUsersReachedError | |||||
test_records = frappe.get_test_records('User') | test_records = frappe.get_test_records('User') | ||||
class TestUser(unittest.TestCase): | 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): | def test_delete(self): | ||||
frappe.get_doc("User", "test@example.com").add_roles("_Test Role 2") | frappe.get_doc("User", "test@example.com").add_roles("_Test Role 2") | ||||
self.assertRaises(frappe.LinkExistsError, delete_doc, "Role", "_Test Role 2") | self.assertRaises(frappe.LinkExistsError, delete_doc, "Role", "_Test Role 2") | ||||
@@ -38,6 +38,9 @@ class User(Document): | |||||
[m.module_name for m in frappe.db.get_all('Desktop Icon', | [m.module_name for m in frappe.db.get_all('Desktop Icon', | ||||
fields=['module_name'], filters={'standard': 1}, order_by="module_name")]) | fields=['module_name'], filters={'standard': 1}, order_by="module_name")]) | ||||
def after_insert(self): | |||||
self.set_default_roles() | |||||
def validate(self): | def validate(self): | ||||
self.check_demo() | self.check_demo() | ||||
@@ -93,6 +96,33 @@ class User(Document): | |||||
if not cint(self.enabled) and getattr(frappe.local, "login_manager", None): | if not cint(self.enabled) and getattr(frappe.local, "login_manager", None): | ||||
frappe.local.login_manager.logout(user=self.name) | 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): | def add_system_manager_role(self): | ||||
# if adding system manager, do nothing | # if adding system manager, do nothing | ||||
if not cint(self.enabled) or ("System Manager" in [user_role.role for user_role in | 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")) | frappe.msgprint(_("New password emailed")) | ||||
def set_system_user(self): | 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' | self.user_type = 'System User' | ||||
else: | else: | ||||
self.user_type = 'Website User' | 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): | def share_with_self(self): | ||||
if self.user_type=="System User": | if self.user_type=="System User": | ||||
frappe.share.add(self.doctype, self.name, self.name, share=1, | frappe.share.add(self.doctype, self.name, self.name, share=1, | ||||
@@ -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} |
@@ -7,11 +7,23 @@ You can also make Previous and Next buttons by adding `previous` or `next` in `{ | |||||
### Showing contents | ### Showing contents | ||||
# This is a title | # This is a title | ||||
Hello paragraph | Hello paragraph | ||||
### Contents: | ### Contents: | ||||
{index} | {index} | ||||
{next} | {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 |
@@ -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): | 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`: | |||||
<h3>List of Users</h3> | |||||
<ol> | |||||
{% for user in users %} | |||||
<li>{{ user.first_name }} {{ user.last_name or "" }}</li> | |||||
{% endfor %} | |||||
</ol> | |||||
{next} | {next} |
@@ -1,7 +1,17 @@ | |||||
# Making Portals | # 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. | 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` | 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} | {index} |
@@ -1,6 +1,6 @@ | |||||
adding-pages | adding-pages | ||||
ordering | |||||
contents | |||||
context | context | ||||
building | |||||
generators | generators | ||||
contents | |||||
web-forms | |||||
portal-roles |
@@ -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 | |||||
<img class="screenshot" src="assets/frappe/img/portals/portal-settings.png"> | |||||
#### 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'} | |||||
] | |||||
@@ -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 | |||||
<img class="screenshot" src="assets/frappe/img/portals/sample-web-form.png"> | |||||
### 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} |
@@ -6,7 +6,7 @@ To create a new Query Report: | |||||
### 1. Create a new Report | ### 1. Create a new Report | ||||
 | |||||
<img class="screenshot" src="assets/frappe/img/query-report.png"> | |||||
1. Set type as "Query Report" | 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 | 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 | ### 3. Check the Report | ||||
 | |||||
<img class="screenshot" src="assets/frappe/img/query-report-out.png"> | |||||
### 4. Advanced (adding filters) | ### 4. Advanced (adding filters) | ||||
@@ -267,8 +267,11 @@ class DatabaseQuery(object): | |||||
if not tname in self.tables: | if not tname in self.tables: | ||||
self.append_table(tname) | 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 | can_be_null = True | ||||
@@ -317,8 +320,10 @@ class DatabaseQuery(object): | |||||
if isinstance(value, basestring): | if isinstance(value, basestring): | ||||
value = '"{0}"'.format(frappe.db.escape(value, percent=False)) | 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( | condition = '{column_name} {operator} {value}'.format( | ||||
column_name=column_name, operator=f.operator, | column_name=column_name, operator=f.operator, | ||||
value=value) | value=value) | ||||
@@ -187,6 +187,14 @@ | |||||
#navbar-breadcrumbs > li > a { | #navbar-breadcrumbs > li > a { | ||||
padding: 6px 15px 10px 0px; | 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 { | .toolbar-user-fullname { | ||||
max-width: 200px; | max-width: 200px; | ||||
display: inline-block; | display: inline-block; | ||||
@@ -31,7 +31,8 @@ def clear_cache(user=None): | |||||
cache = frappe.cache() | cache = frappe.cache() | ||||
groups = ("bootinfo", "user_recent", "user_roles", "user_doc", "lang", | 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: | if user: | ||||
for name in groups: | for name in groups: | ||||
@@ -3,7 +3,6 @@ | |||||
from __future__ import unicode_literals | from __future__ import unicode_literals | ||||
import frappe | import frappe | ||||
import json | |||||
from frappe.website.doctype.website_settings.website_settings import get_website_settings | from frappe.website.doctype.website_settings.website_settings import get_website_settings | ||||
from frappe.website.router import get_page_context | from frappe.website.router import get_page_context | ||||
@@ -83,7 +82,7 @@ def build_context(context): | |||||
elif context.controller: | elif context.controller: | ||||
# controller based context | # controller based context | ||||
update_controller_context(context, context.controller) | update_controller_context(context, context.controller) | ||||
# controller context extensions | # controller context extensions | ||||
context_controller_hooks = frappe.get_hooks("extend_website_page_controller_context") or {} | context_controller_hooks = frappe.get_hooks("extend_website_page_controller_context") or {} | ||||
for controller, extension in context_controller_hooks.items(): | for controller, extension in context_controller_hooks.items(): | ||||
@@ -96,6 +95,9 @@ def build_context(context): | |||||
add_metatags(context) | add_metatags(context) | ||||
if frappe.session.user == 'Guest': | |||||
context.show_sidebar = 0 | |||||
if context.show_sidebar: | if context.show_sidebar: | ||||
add_sidebar_data(context) | add_sidebar_data(context) | ||||
@@ -111,13 +113,17 @@ def add_sidebar_data(context): | |||||
import frappe.www.list | import frappe.www.list | ||||
if not context.sidebar_items: | 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', | 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') | 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 | context.sidebar_items = sidebar_items | ||||
@@ -14,7 +14,7 @@ | |||||
"allow_on_submit": 0, | "allow_on_submit": 0, | ||||
"bold": 0, | "bold": 0, | ||||
"collapsible": 0, | "collapsible": 0, | ||||
"columns": 0, | |||||
"columns": 2, | |||||
"fieldname": "title", | "fieldname": "title", | ||||
"fieldtype": "Data", | "fieldtype": "Data", | ||||
"hidden": 0, | "hidden": 0, | ||||
@@ -40,7 +40,7 @@ | |||||
"allow_on_submit": 0, | "allow_on_submit": 0, | ||||
"bold": 0, | "bold": 0, | ||||
"collapsible": 0, | "collapsible": 0, | ||||
"columns": 0, | |||||
"columns": 1, | |||||
"fieldname": "enabled", | "fieldname": "enabled", | ||||
"fieldtype": "Check", | "fieldtype": "Check", | ||||
"hidden": 0, | "hidden": 0, | ||||
@@ -66,7 +66,7 @@ | |||||
"allow_on_submit": 0, | "allow_on_submit": 0, | ||||
"bold": 0, | "bold": 0, | ||||
"collapsible": 0, | "collapsible": 0, | ||||
"columns": 0, | |||||
"columns": 3, | |||||
"fieldname": "route", | "fieldname": "route", | ||||
"fieldtype": "Data", | "fieldtype": "Data", | ||||
"hidden": 0, | "hidden": 0, | ||||
@@ -92,7 +92,7 @@ | |||||
"allow_on_submit": 0, | "allow_on_submit": 0, | ||||
"bold": 0, | "bold": 0, | ||||
"collapsible": 0, | "collapsible": 0, | ||||
"columns": 0, | |||||
"columns": 2, | |||||
"description": "", | "description": "", | ||||
"fieldname": "reference_doctype", | "fieldname": "reference_doctype", | ||||
"fieldtype": "Link", | "fieldtype": "Link", | ||||
@@ -120,22 +120,23 @@ | |||||
"allow_on_submit": 0, | "allow_on_submit": 0, | ||||
"bold": 0, | "bold": 0, | ||||
"collapsible": 0, | "collapsible": 0, | ||||
"columns": 0, | |||||
"fieldname": "target", | |||||
"fieldtype": "Data", | |||||
"columns": 2, | |||||
"fieldname": "role", | |||||
"fieldtype": "Link", | |||||
"hidden": 0, | "hidden": 0, | ||||
"ignore_user_permissions": 0, | "ignore_user_permissions": 0, | ||||
"ignore_xss_filter": 0, | "ignore_xss_filter": 0, | ||||
"in_filter": 0, | "in_filter": 0, | ||||
"in_list_view": 0, | |||||
"label": "Target", | |||||
"in_list_view": 1, | |||||
"label": "Role", | |||||
"length": 0, | "length": 0, | ||||
"no_copy": 0, | "no_copy": 0, | ||||
"options": "Role", | |||||
"permlevel": 0, | "permlevel": 0, | ||||
"precision": "", | "precision": "", | ||||
"print_hide": 0, | "print_hide": 0, | ||||
"print_hide_if_no_value": 0, | "print_hide_if_no_value": 0, | ||||
"read_only": 1, | |||||
"read_only": 0, | |||||
"report_hide": 0, | "report_hide": 0, | ||||
"reqd": 0, | "reqd": 0, | ||||
"search_index": 0, | "search_index": 0, | ||||
@@ -147,21 +148,21 @@ | |||||
"bold": 0, | "bold": 0, | ||||
"collapsible": 0, | "collapsible": 0, | ||||
"columns": 0, | "columns": 0, | ||||
"fieldname": "show_always", | |||||
"fieldtype": "Check", | |||||
"fieldname": "target", | |||||
"fieldtype": "Data", | |||||
"hidden": 0, | "hidden": 0, | ||||
"ignore_user_permissions": 0, | "ignore_user_permissions": 0, | ||||
"ignore_xss_filter": 0, | "ignore_xss_filter": 0, | ||||
"in_filter": 0, | "in_filter": 0, | ||||
"in_list_view": 0, | "in_list_view": 0, | ||||
"label": "Show Always", | |||||
"label": "Target", | |||||
"length": 0, | "length": 0, | ||||
"no_copy": 0, | "no_copy": 0, | ||||
"permlevel": 0, | "permlevel": 0, | ||||
"precision": "", | "precision": "", | ||||
"print_hide": 0, | "print_hide": 0, | ||||
"print_hide_if_no_value": 0, | "print_hide_if_no_value": 0, | ||||
"read_only": 0, | |||||
"read_only": 1, | |||||
"report_hide": 0, | "report_hide": 0, | ||||
"reqd": 0, | "reqd": 0, | ||||
"search_index": 0, | "search_index": 0, | ||||
@@ -179,7 +180,7 @@ | |||||
"issingle": 0, | "issingle": 0, | ||||
"istable": 1, | "istable": 1, | ||||
"max_attachments": 0, | "max_attachments": 0, | ||||
"modified": "2016-09-13 13:08:58.890253", | |||||
"modified": "2016-09-23 05:42:17.928917", | |||||
"modified_by": "Administrator", | "modified_by": "Administrator", | ||||
"module": "Website", | "module": "Website", | ||||
"name": "Portal Menu Item", | "name": "Portal Menu Item", | ||||
@@ -2,16 +2,46 @@ | |||||
"allow_copy": 0, | "allow_copy": 0, | ||||
"allow_import": 0, | "allow_import": 0, | ||||
"allow_rename": 0, | "allow_rename": 0, | ||||
"beta": 0, | |||||
"creation": "2016-03-30 01:40:20.001775", | "creation": "2016-03-30 01:40:20.001775", | ||||
"custom": 0, | "custom": 0, | ||||
"docstatus": 0, | "docstatus": 0, | ||||
"doctype": "DocType", | "doctype": "DocType", | ||||
"document_type": "", | "document_type": "", | ||||
"editable_grid": 0, | |||||
"fields": [ | "fields": [ | ||||
{ | { | ||||
"allow_on_submit": 0, | "allow_on_submit": 0, | ||||
"bold": 0, | "bold": 0, | ||||
"collapsible": 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", | "fieldname": "menu", | ||||
"fieldtype": "Table", | "fieldtype": "Table", | ||||
"hidden": 0, | "hidden": 0, | ||||
@@ -38,13 +68,14 @@ | |||||
"hide_heading": 0, | "hide_heading": 0, | ||||
"hide_toolbar": 0, | "hide_toolbar": 0, | ||||
"idx": 0, | "idx": 0, | ||||
"image_view": 0, | |||||
"in_create": 0, | "in_create": 0, | ||||
"in_dialog": 0, | "in_dialog": 0, | ||||
"is_submittable": 0, | "is_submittable": 0, | ||||
"issingle": 1, | "issingle": 1, | ||||
"istable": 0, | "istable": 0, | ||||
"max_attachments": 0, | "max_attachments": 0, | ||||
"modified": "2016-03-30 01:40:20.001775", | |||||
"modified": "2016-09-23 06:34:18.718351", | |||||
"modified_by": "Administrator", | "modified_by": "Administrator", | ||||
"module": "Website", | "module": "Website", | ||||
"name": "Portal Settings", | "name": "Portal Settings", | ||||
@@ -72,6 +103,7 @@ | |||||
"write": 1 | "write": 1 | ||||
} | } | ||||
], | ], | ||||
"quick_entry": 0, | |||||
"read_only": 0, | "read_only": 0, | ||||
"read_only_onload": 0, | "read_only_onload": 0, | ||||
"sort_field": "modified", | "sort_field": "modified", | ||||
@@ -8,8 +8,13 @@ from frappe.model.document import Document | |||||
class PortalSettings(Document): | class PortalSettings(Document): | ||||
def add_item(self, item): | 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 | item['enabled'] = 1 | ||||
self.append('menu', item) | self.append('menu', item) | ||||
return True | return True | ||||
@@ -29,3 +34,18 @@ class PortalSettings(Document): | |||||
if dirty: | if dirty: | ||||
self.save() | 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() | |||||
@@ -499,6 +499,33 @@ | |||||
"set_only_once": 0, | "set_only_once": 0, | ||||
"unique": 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, | "allow_on_submit": 0, | ||||
"bold": 0, | "bold": 0, | ||||
@@ -618,7 +645,7 @@ | |||||
"issingle": 0, | "issingle": 0, | ||||
"istable": 0, | "istable": 0, | ||||
"max_attachments": 0, | "max_attachments": 0, | ||||
"modified": "2016-09-20 07:06:10.839930", | |||||
"modified": "2016-09-23 06:48:31.461495", | |||||
"modified_by": "Administrator", | "modified_by": "Administrator", | ||||
"module": "Website", | "module": "Website", | ||||
"name": "Web Form", | "name": "Web Form", | ||||
@@ -93,7 +93,6 @@ def get_context(context): | |||||
""") | """) | ||||
def get_context(self, context): | def get_context(self, context): | ||||
context.show_sidebar=True | |||||
from frappe.www.list import get_context as get_list_context | from frappe.www.list import get_context as get_list_context | ||||
frappe.form_dict.is_web_form = 1 | frappe.form_dict.is_web_form = 1 | ||||
@@ -67,7 +67,7 @@ class WebPage(WebsiteGenerator): | |||||
def set_breadcrumbs(self, context): | def set_breadcrumbs(self, context): | ||||
"""Build breadcrumbs template (deprecated)""" | """Build breadcrumbs template (deprecated)""" | ||||
if not "no_breadcrumbs" in context: | if not "no_breadcrumbs" in context: | ||||
if "<!-- no-breadcrumbs -->" in context.main_section: | |||||
if "<!-- no-breadcrumbs -->" in context.main_section or '': | |||||
context.no_breadcrumbs = 1 | context.no_breadcrumbs = 1 | ||||
def set_title_and_header(self, context): | def set_title_and_header(self, context): | ||||