feat: introduce /portal
This commit is contained in:
parent
1dece29b80
commit
46f6c7481f
5 changed files with 169 additions and 1 deletions
31
frappe/website/page_renderers/portal_renderer.py
Normal file
31
frappe/website/page_renderers/portal_renderer.py
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
import frappe
|
||||
from frappe.website.page_renderers.template_page import TemplatePage
|
||||
from frappe.website.utils import check_if_webform_exists
|
||||
|
||||
|
||||
class PortalPage(TemplatePage):
|
||||
def can_render(self):
|
||||
parts = self.path.split("/", 1)
|
||||
if len(parts) >= 2:
|
||||
menu_item = frappe.db.exists(
|
||||
"Portal Menu Item",
|
||||
{"route": f"/{parts[1]}"},
|
||||
)
|
||||
|
||||
if check_if_webform_exists(parts[1]):
|
||||
return False
|
||||
|
||||
if parts[0] == "portal" and menu_item:
|
||||
self.ref_doctype = frappe.db.get_value(
|
||||
"Portal Menu Item",
|
||||
menu_item,
|
||||
"reference_doctype",
|
||||
)
|
||||
return self.ref_doctype
|
||||
|
||||
return False
|
||||
|
||||
def render(self):
|
||||
frappe.form_dict.doctype = self.ref_doctype
|
||||
self.set_standard_path("portal")
|
||||
return super().render()
|
||||
|
|
@ -7,13 +7,14 @@ from werkzeug.routing import Rule
|
|||
import frappe
|
||||
from frappe.website.page_renderers.document_page import DocumentPage
|
||||
from frappe.website.page_renderers.not_found_page import NotFoundPage
|
||||
from frappe.website.page_renderers.portal_renderer import PortalPage
|
||||
from frappe.website.page_renderers.print_page import PrintPage
|
||||
from frappe.website.page_renderers.redirect_page import RedirectPage
|
||||
from frappe.website.page_renderers.static_page import StaticPage
|
||||
from frappe.website.page_renderers.template_page import TemplatePage
|
||||
from frappe.website.page_renderers.web_form import WebFormPage
|
||||
from frappe.website.router import evaluate_dynamic_routes
|
||||
from frappe.website.utils import can_cache, get_home_page
|
||||
from frappe.website.utils import can_cache, check_if_webform_exists, get_home_page
|
||||
|
||||
|
||||
class PathResolver:
|
||||
|
|
@ -60,6 +61,7 @@ class PathResolver:
|
|||
DocumentPage,
|
||||
TemplatePage,
|
||||
PrintPage,
|
||||
PortalPage,
|
||||
]
|
||||
|
||||
for renderer in renderers:
|
||||
|
|
@ -135,6 +137,7 @@ def resolve_redirect(path, query_string=None):
|
|||
return
|
||||
|
||||
redirects = frappe.get_hooks("website_redirects")
|
||||
redirects += add_portal_redirect()
|
||||
redirects += [
|
||||
{
|
||||
"source": r.source,
|
||||
|
|
@ -226,3 +229,20 @@ def get_website_rules():
|
|||
def validate_path(path: str):
|
||||
if not PathResolver(path).is_valid_path():
|
||||
frappe.throw(frappe._("Path {0} it not a valid path").format(frappe.bold(path)))
|
||||
|
||||
|
||||
def add_portal_redirect():
|
||||
redirects = []
|
||||
menu_items = frappe.get_single("Portal Settings").menu
|
||||
|
||||
for item in menu_items:
|
||||
if check_if_webform_exists(item.route):
|
||||
continue
|
||||
redirects.append(
|
||||
{
|
||||
"source": item.route,
|
||||
"target": f"/portal{item.route}",
|
||||
"formward_query_parameters": True,
|
||||
}
|
||||
)
|
||||
return redirects
|
||||
|
|
|
|||
|
|
@ -607,3 +607,9 @@ def is_binary_file(path):
|
|||
with open(path, "rb") as f:
|
||||
content = f.read(1024)
|
||||
return bool(content.translate(None, textchars))
|
||||
|
||||
|
||||
def check_if_webform_exists(route):
|
||||
return frappe.db.exists("Web Form", {"name": route.strip("/")}) or frappe.db.exists(
|
||||
"Web Form", {"route": route.strip("/")}
|
||||
)
|
||||
|
|
|
|||
27
frappe/www/portal.html
Normal file
27
frappe/www/portal.html
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
{% extends "templates/web.html" %}
|
||||
{% block footer %}{% endblock %}
|
||||
|
||||
|
||||
{% block header %}
|
||||
{% if doctype %}
|
||||
<h3 class="my-account-header">
|
||||
{{ title or (_("{0} List").format(_(doctype))) }}
|
||||
</h3>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block page_content %}
|
||||
{% if not doctype %}
|
||||
<h2>Welcome to the Portal</h2>
|
||||
{% else %}
|
||||
{% if introduction %}
|
||||
<p>{{ introduction }}</p>
|
||||
{% endif %}
|
||||
|
||||
{% include list_template %}
|
||||
|
||||
{% if list_footer %}
|
||||
{{ list_footer }}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
84
frappe/www/portal.py
Normal file
84
frappe/www/portal.py
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
import json
|
||||
|
||||
import frappe
|
||||
from frappe import _, cint
|
||||
from frappe.model.document import Document
|
||||
from frappe.utils.data import quoted
|
||||
from frappe.www.list import get_list_context, get_list_data
|
||||
|
||||
|
||||
def get_context(context, **dict_params):
|
||||
frappe.local.form_dict.update(dict_params)
|
||||
context.show_sidebar = True
|
||||
doctype = frappe.local.form_dict.doctype
|
||||
if doctype:
|
||||
context.meta = frappe.get_meta(doctype)
|
||||
context.update(get_list_context(context, doctype) or {})
|
||||
context.update(get(**frappe.local.form_dict))
|
||||
context.home_page = "/portal"
|
||||
context.doctype = frappe.local.form_dict.doctype
|
||||
return context
|
||||
|
||||
|
||||
def set_route(context):
|
||||
"""Set link for the list item"""
|
||||
if context.web_form_name:
|
||||
context.route = f"{context.pathname}?name={quoted(context.doc.name)}"
|
||||
elif context.doc and getattr(context.doc, "route", None):
|
||||
context.route = context.doc.route
|
||||
else:
|
||||
context.route = f"{context.pathname or quoted(context.doc.doctype)}/{quoted(context.doc.name)}"
|
||||
|
||||
|
||||
def get(
|
||||
doctype: str,
|
||||
txt: str | None = None,
|
||||
limit_start: int = 0,
|
||||
limit: int = 20,
|
||||
pathname: str | None = None,
|
||||
**kwargs,
|
||||
):
|
||||
"""Return processed HTML page for a standard listing."""
|
||||
limit_start = cint(limit_start)
|
||||
raw_result = get_list_data(doctype, txt, limit_start, limit=limit + 1, **kwargs)
|
||||
show_more = len(raw_result) > limit
|
||||
if show_more:
|
||||
raw_result = raw_result[:-1]
|
||||
|
||||
meta = frappe.get_meta(doctype)
|
||||
list_context = frappe.flags.list_context
|
||||
|
||||
if not raw_result:
|
||||
return {"result": []}
|
||||
|
||||
if txt:
|
||||
list_context.default_subtitle = _('Filtered by "{0}"').format(txt)
|
||||
|
||||
result = []
|
||||
row_template = list_context.row_template or "templates/includes/list/row_template.html"
|
||||
list_view_fields = [df for df in meta.fields if df.in_list_view][:4]
|
||||
|
||||
for doc in raw_result:
|
||||
doc.doctype = doctype
|
||||
new_context = frappe._dict(doc=doc, meta=meta, list_view_fields=list_view_fields)
|
||||
|
||||
if not list_context.get_list and not isinstance(new_context.doc, Document):
|
||||
new_context.doc = frappe.get_doc(doc.doctype, doc.name)
|
||||
new_context.update(new_context.doc.as_dict())
|
||||
|
||||
if not frappe.in_test:
|
||||
pathname = pathname or frappe.local.request.path
|
||||
new_context["pathname"] = pathname.strip("/ ")
|
||||
new_context.update(list_context)
|
||||
set_route(new_context)
|
||||
rendered_row = frappe.render_template(row_template, new_context, is_path=True)
|
||||
result.append(rendered_row)
|
||||
|
||||
from frappe.utils.response import json_handler
|
||||
|
||||
return {
|
||||
"raw_result": json.dumps(raw_result, default=json_handler),
|
||||
"result": result,
|
||||
"show_more": show_more,
|
||||
"next_start": limit_start + limit,
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue