Merge pull request #9999 from rmehta/webview-fixes-1

fix(web view): Made Web Views embeddable & other enhancements
This commit is contained in:
Rushabh Mehta 2020-04-20 10:28:08 +05:30 committed by GitHub
commit b7b0f1ddb1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
24 changed files with 510 additions and 402 deletions

View file

@ -20,7 +20,7 @@ class TestExporter(unittest.TestCase):
e = Exporter('Web Page', export_fields='All')
csv_array = e.get_csv_array()
header = csv_array[0]
self.assertEqual(len(header), 24)
self.assertEqual(len(header), 28)
def test_exports_selected_fields(self):

View file

@ -196,8 +196,6 @@ class FormMeta(Meta):
self.get("__messages").update(messages, as_value=True)
def load_dashboard(self):
if self.custom:
return
self.set('__dashboard', self.get_dashboard_data())
def load_kanban_meta(self):

View file

@ -425,17 +425,19 @@ class Meta(Document):
implemented in other Frappe applications via hooks.
'''
data = frappe._dict()
try:
module = load_doctype_module(self.name, suffix='_dashboard')
if hasattr(module, 'get_data'):
data = frappe._dict(module.get_data())
except ImportError:
pass
if not self.custom:
try:
module = load_doctype_module(self.name, suffix='_dashboard')
if hasattr(module, 'get_data'):
data = frappe._dict(module.get_data())
except ImportError:
pass
self.add_doctype_links(data)
for hook in frappe.get_hooks("override_doctype_dashboards", {}).get(self.name, []):
data = frappe.get_attr(hook)(data=data)
if not self.custom:
for hook in frappe.get_hooks("override_doctype_dashboards", {}).get(self.name, []):
data = frappe.get_attr(hook)(data=data)
return data

View file

@ -23,6 +23,17 @@ footer {
flex-shrink: 0;
}
// make navbar padding consistent with the page
.navbar {
padding-left: 0;
padding-right: 0;
.container {
padding-left: 15px;
padding-right: 15px;
}
}
.navbar.bg-dark {
.dropdown-menu {
font-size: .75rem;

View file

@ -13,7 +13,7 @@
</div>
{% block page_container %}
<main class="{% if not theme.use_full_width %}container{% endif %} my-5">
<main class="{% if not full_width %}container my-5{% endif %}">
<div class="d-flex justify-content-between align-items-center">
<div class="page-header">
{% block header %}{% endblock %}
@ -38,9 +38,11 @@
</div>
{% endmacro %}
{% macro container_attributes() %}
id="page-{{ name or route | e }}" data-path="{{ pathname | e }}" {%- if page_or_generator=="Generator" %}source-type="Generator" data-doctype="{{ doctype }}"{% endif %}
{% endmacro %}
{% macro container_attributes() -%}
id="page-{{ name or route | e }}" data-path="{{ pathname | e }}"
{%- if page_or_generator=="Generator" %}source-type="Generator" data-doctype="{{ doctype }}"{%- endif %}
{%- if source_content_type %}source-content-type="{{ source_content_type }}"{%- endif %}
{%- endmacro %}
{% if show_sidebar %}
<div class="container">

View file

@ -221,24 +221,24 @@ def add_metatags(context):
tags = frappe._dict(context.get("metatags") or {})
if tags:
if not "twitter:card" in tags:
tags["twitter:card"] = "summary_large_image"
if not "og:type" in tags:
tags["og:type"] = "article"
if tags.get("name"):
tags["og:title"] = tags["twitter:title"] = tags["name"]
name = tags.get('name') or tags.get('title')
if name:
tags["og:title"] = tags["twitter:title"] = name
if tags.get("title"):
tags["og:title"] = tags["twitter:title"] = tags["title"]
if tags.get("description"):
tags["og:description"] = tags["twitter:description"] = tags["description"]
description = tags.get("description") or context.description
if description:
tags['description'] = tags["og:description"] = tags["twitter:description"] = description
image = tags.get('image', context.image or None)
if image:
tags["og:image"] = tags["twitter:image:src"] = tags["image"] = frappe.utils.get_url(image)
tags['twitter:card'] = "summary_large_image"
if context.author or tags.get('author'):
tags['author'] = context.author or tags.get('author')
if context.path:
tags['og:url'] = tags['url'] = frappe.utils.get_url(context.path)
@ -246,11 +246,6 @@ def add_metatags(context):
if context.published_on:
tags['datePublished'] = context.published_on
if context.author:
tags['author'] = context.author
if context.description:
tags['description'] = context.description
tags['language'] = frappe.local.lang or 'en'

View file

@ -1,274 +1,108 @@
{
"allow_copy": 0,
"allow_import": 1,
"allow_rename": 0,
"autoname": "field:short_name",
"beta": 0,
"creation": "2013-03-25 16:00:51",
"custom": 0,
"description": "User ID of a Blogger",
"docstatus": 0,
"doctype": "DocType",
"document_type": "Setup",
"editable_grid": 0,
"actions": [],
"allow_import": 1,
"autoname": "field:short_name",
"creation": "2013-03-25 16:00:51",
"description": "User ID of a Blogger",
"doctype": "DocType",
"document_type": "Setup",
"engine": "InnoDB",
"field_order": [
"disabled",
"short_name",
"full_name",
"user",
"bio",
"avatar",
"posts"
],
"fields": [
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "disabled",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Disabled",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
"default": "0",
"fieldname": "disabled",
"fieldtype": "Check",
"label": "Disabled"
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"description": "Will be used in url (usually first name).",
"fieldname": "short_name",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Short Name",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
"description": "Will be used in url (usually first name).",
"fieldname": "short_name",
"fieldtype": "Data",
"label": "Short Name",
"reqd": 1,
"unique": 1
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "full_name",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Full Name",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
"fieldname": "full_name",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Full Name",
"reqd": 1
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "user",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "User",
"length": 0,
"no_copy": 0,
"options": "User",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
"fieldname": "user",
"fieldtype": "Link",
"label": "User",
"options": "User"
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "bio",
"fieldtype": "Small Text",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Bio",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
"fieldname": "bio",
"fieldtype": "Small Text",
"label": "Bio"
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "avatar",
"fieldtype": "Attach",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Avatar",
"length": 0,
"no_copy": 0,
"options": "",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
"fieldname": "avatar",
"fieldtype": "Attach",
"label": "Avatar"
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "posts",
"fieldtype": "Int",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Posts",
"length": 0,
"no_copy": 1,
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
"fieldname": "posts",
"fieldtype": "Int",
"in_list_view": 1,
"label": "Posts",
"no_copy": 1,
"read_only": 1
}
],
"hide_heading": 0,
"hide_toolbar": 0,
"icon": "fa fa-user",
"idx": 1,
"image_view": 0,
"in_create": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 0,
"max_attachments": 1,
"modified": "2018-10-10 14:40:40.407657",
"modified_by": "Administrator",
"module": "Website",
"name": "Blogger",
"owner": "Administrator",
],
"icon": "fa fa-user",
"idx": 1,
"links": [
{
"link_doctype": "Blog Post",
"link_fieldname": "blogger"
}
],
"max_attachments": 1,
"modified": "2020-04-19 08:21:09.684300",
"modified_by": "Administrator",
"module": "Website",
"name": "Blogger",
"owner": "Administrator",
"permissions": [
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"if_owner": 0,
"import": 1,
"is_custom": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Website Manager",
"set_user_permissions": 1,
"share": 1,
"submit": 0,
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"import": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "Website Manager",
"set_user_permissions": 1,
"share": 1,
"write": 1
},
},
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 0,
"delete": 0,
"email": 1,
"export": 0,
"if_owner": 0,
"import": 0,
"is_custom": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 0,
"role": "Blogger",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"email": 1,
"print": 1,
"read": 1,
"role": "Blogger",
"share": 1,
"write": 1
}
],
"quick_entry": 0,
"read_only": 0,
"read_only_onload": 0,
"title_field": "full_name",
"track_changes": 1,
"track_seen": 0
],
"sort_field": "modified",
"sort_order": "DESC",
"title_field": "full_name",
"track_changes": 1
}

View file

@ -0,0 +1,8 @@
// Copyright (c) 2020, Frappe Technologies and contributors
// For license information, please see license.txt
frappe.ui.form.on('Color', {
// refresh: function(frm) {
// }
});

View file

@ -0,0 +1,44 @@
{
"actions": [],
"autoname": "Prompt",
"creation": "2020-04-19 02:25:37.010180",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"color"
],
"fields": [
{
"fieldname": "color",
"fieldtype": "Color",
"in_list_view": 1,
"label": "Color",
"reqd": 1
}
],
"links": [],
"modified": "2020-04-19 02:25:47.417772",
"modified_by": "Administrator",
"module": "Website",
"name": "Color",
"owner": "Administrator",
"permissions": [
{
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "Website Manager",
"share": 1,
"write": 1
}
],
"quick_entry": 1,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1
}

View file

@ -6,5 +6,5 @@ from __future__ import unicode_literals
# import frappe
from frappe.model.document import Document
class WebViewItem(Document):
class Color(Document):
pass

View file

@ -0,0 +1,10 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2020, Frappe Technologies and Contributors
# See license.txt
from __future__ import unicode_literals
# import frappe
import unittest
class TestColor(unittest.TestCase):
pass

View file

@ -1,4 +1,5 @@
{
"actions": [],
"allow_guest_to_view": 1,
"allow_import": 1,
"creation": "2013-03-28 10:35:30",
@ -13,6 +14,7 @@
"slideshow",
"cb1",
"published",
"full_width",
"show_title",
"start_date",
"end_date",
@ -39,6 +41,10 @@
"sb2",
"header",
"breadcrumbs",
"metatags_section",
"meta_title",
"meta_description",
"meta_image",
"set_meta_tags"
],
"fields": [
@ -217,7 +223,7 @@
"depends_on": "eval:!doc.__islocal",
"fieldname": "sb2",
"fieldtype": "Section Break",
"label": "Header, Breadcrumbs and Meta Tags"
"label": "Header and Breadcrumbs"
},
{
"description": "HTML for header section. Optional",
@ -235,21 +241,49 @@
{
"fieldname": "set_meta_tags",
"fieldtype": "Button",
"label": "Set Meta Tags"
"label": "Add Custom Tags"
},
{
"default": "0",
"fieldname": "dynamic_template",
"fieldtype": "Check",
"label": "Dynamic Template"
},
{
"default": "0",
"fieldname": "full_width",
"fieldtype": "Check",
"label": "Full Width"
},
{
"collapsible": 1,
"fieldname": "metatags_section",
"fieldtype": "Section Break",
"label": "Meta Tags"
},
{
"fieldname": "meta_title",
"fieldtype": "Data",
"label": "Title"
},
{
"fieldname": "meta_description",
"fieldtype": "Small Text",
"label": "Description"
},
{
"fieldname": "meta_image",
"fieldtype": "Attach Image",
"label": "Image"
}
],
"has_web_view": 1,
"icon": "fa fa-file-alt",
"idx": 1,
"is_published_field": "published",
"links": [],
"max_attachments": 20,
"modified": "2019-10-02 13:58:50.825481",
"modified": "2020-04-19 12:26:21.546908",
"modified_by": "Administrator",
"module": "Website",
"name": "Web Page",

View file

@ -36,6 +36,7 @@ class WebPage(WebsiteGenerator):
def get_context(self, context):
context.main_section = get_html_content_based_on_type(self, 'main_section', self.content_type)
context.source_content_type = self.content_type
self.render_dynamic(context)
# if static page, get static content
@ -127,13 +128,11 @@ class WebPage(WebsiteGenerator):
def set_metatags(self, context):
context.metatags = {
"name": context.title
"name": self.meta_title or self.title,
"description": self.meta_description,
"image": self.meta_image or find_first_image(context.main_section or "")
}
image = find_first_image(context.main_section or "")
if image:
context.metatags["image"] = image
def validate_dates(self):
if self.end_date:
if self.start_date and get_datetime(self.end_date) < get_datetime(self.start_date):

View file

@ -9,7 +9,7 @@
{%- endif -%}
{%- macro render_element(element) -%}
{%- if element.element_type=='Content' -%}
{%- if element.element_type in ('Content', 'Web View') -%}
<div class="web-content {{ element_class(element) }}" {{ element_style(element) }}>
{{ element.web_content_html }}
</div>
@ -25,17 +25,16 @@
{%- endmacro -%}
{%- macro element_style(element) -%}
{%- if element.element_style -%}
style = "{{ element.element_style }}"
{%- if element.element_style or element.background_color -%}
style = "{{ element.element_style or '' }} {%if element.background_color %}background-color: {{ element.background_color }};{% endif %}"
{%- endif -%}
{%- endmacro -%}
{%- macro render_sections(sections) -%}
{%- for section in sections -%}
<section class='section {{ section.element_class or "" }} {{ section.hide and "hidden" or "" }}'>
<div class='section-body container'>
<section class='section {{ section.element_class or "" }} {{ section.hide and "hidden" or "" }}' {{ element_style(section) }}>
<div class='section-body {% if section.contain_section_width %}container{% endif %}'>
{%- if section.section_intro -%}
<div class='section-intro'>{{ section.section_intro }}</div>
{%- endif -%}
@ -74,4 +73,11 @@
{%- endif -%}
</div>
</section>
{%- endfor -%}
{%- endfor -%}
{%- endmacro -%}
{% if content_type == 'HTML' -%}
{{ content_html }}
{%- else -%}
{{ render_sections(sections) }}
{%- endif -%}

View file

@ -14,6 +14,7 @@ class TestWebView(unittest.TestCase):
@classmethod
def setUpClass(cls):
frappe.delete_doc_if_exists('Web View', 'test-web-view')
frappe.delete_doc_if_exists('Web View', 'html-web-view')
frappe.delete_doc_if_exists('CSS Class', 'test-css-class')
frappe.get_doc(dict(
@ -22,12 +23,25 @@ class TestWebView(unittest.TestCase):
css = '.test-class { color: red; }'
)).insert()
# simple html webview
frappe.get_doc(dict(
doctype = 'Web View',
title = 'HTML Web View',
route = 'html-web-view',
published = 1,
content_type = 'HTML',
content_html = '<h1>Hello HTML</h1>'
)).insert()
# simple web view with components
frappe.get_doc(dict(
doctype = 'Web View',
title = 'Test Web View',
route = 'test-web-view',
published = 1,
items = [
content_type = 'Components',
components = [
dict(
element_type = 'Section',
section_type = 'List'
@ -57,19 +71,27 @@ class TestWebView(unittest.TestCase):
web_content_type = 'Markdown',
web_content_markdown = 'Column 2'
),
dict(
element_type = 'Web View',
web_view = 'html-web-view',
),
]
)).insert()
def test_web_view(self):
html = get_page_content('test-web-view')
#print(html)
self.assert_web_view_in_html(html)
def test_html_web_view(self):
html = get_page_content('html-web-view')
self.assertTrue('Hello HTML' in html)
def assert_web_view_in_html(self, html):
self.assertTrue('<h2 id="heading">Heading</h2>' in html)
self.assertTrue('<div>Here is some HTML</div>' in html)
self.assertTrue('Column 1' in html)
self.assertTrue('Column 2' in html)
self.assertTrue('Hello HTML' in html)
self.assertTrue('.test-class { color: red; }' in html)
def test_web_view_in_footer(self):

View file

@ -12,18 +12,21 @@
"field_order": [
"title",
"route",
"column_break_4",
"full_width",
"published",
"items",
"css"
"section_break_6",
"content_type",
"content_html",
"components",
"style_section",
"css",
"metatags_section",
"meta_title",
"meta_description",
"meta_image"
],
"fields": [
{
"fieldname": "items",
"fieldtype": "Table",
"label": "Items",
"options": "Web View Item",
"reqd": 1
},
{
"fieldname": "title",
"fieldtype": "Data",
@ -36,8 +39,7 @@
"fieldname": "route",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Route",
"reqd": 1
"label": "Route"
},
{
"default": "0",
@ -49,12 +51,73 @@
"fieldname": "css",
"fieldtype": "Code",
"label": "CSS"
},
{
"fieldname": "column_break_4",
"fieldtype": "Column Break"
},
{
"default": "0",
"fieldname": "full_width",
"fieldtype": "Check",
"label": "Full Width"
},
{
"fieldname": "section_break_6",
"fieldtype": "Section Break",
"label": "Content"
},
{
"default": "Components",
"fieldname": "content_type",
"fieldtype": "Select",
"label": "Content Type",
"options": "Components\nHTML",
"reqd": 1
},
{
"depends_on": "eval:doc.content_type==='Components'",
"fieldname": "components",
"fieldtype": "Table",
"label": "Components",
"options": "Web View Component"
},
{
"depends_on": "eval:doc.content_type===\"HTML\"",
"fieldname": "content_html",
"fieldtype": "HTML Editor",
"label": "Content HTML"
},
{
"fieldname": "style_section",
"fieldtype": "Section Break",
"label": "Style"
},
{
"fieldname": "metatags_section",
"fieldtype": "Section Break",
"label": "Meta Tags"
},
{
"fieldname": "meta_title",
"fieldtype": "Data",
"label": "Title"
},
{
"fieldname": "meta_description",
"fieldtype": "Small Text",
"label": "Description"
},
{
"fieldname": "meta_image",
"fieldtype": "Attach Image",
"label": "Image"
}
],
"has_web_view": 1,
"is_published_field": "published",
"links": [],
"modified": "2020-04-15 23:58:12.208049",
"modified": "2020-04-19 12:25:48.014935",
"modified_by": "Administrator",
"module": "Website",
"name": "Web View",

View file

@ -10,49 +10,71 @@ import frappe
class WebView(WebsiteGenerator):
def get_context(self, context):
# group items into sections
# group components into sections
if self.content_type=='Components':
self.build_components(context)
self.set_metatags(context)
return context
def build_components(self, context):
context.sections = []
context.css_rules = []
for item in self.items:
if not context.sections and item.element_type!='Section':
for component in self.components:
if not context.sections and component.element_type!='Section':
self.add_default_section(context)
if item.element_type=='Section':
self.add_section(context, item)
if component.element_type=='Section':
self.add_section(context, component)
else:
self.add_item(context, item)
self.add_component(context, component)
self.add_css_class(context, item)
self.add_css_class(context, component)
self.add_color(component)
self.add_missing_semi(component)
return context
def add_section(self, context, item):
item.elements = []
context.sections.append(item)
def add_section(self, context, component):
component.elements = []
context.sections.append(component)
if item.section_intro:
item.section_intro = markdown(item.section_intro)
if component.section_intro:
component.section_intro = markdown(component.section_intro)
def add_item(self, context, item):
if item.hide:
def add_component(self, context, component):
if component.hide:
return
if item.web_content_type == 'Markdown':
item.web_content_html = markdown(item.web_content_markdown)
if component.element_type == 'Web View' and component.web_view:
component.web_content_html = frappe.get_doc('Web View', component.web_view).render_content()
if item.title:
item.element_id = frappe.scrub(item.title)
elif component.web_content_type == 'Markdown':
component.web_content_html = markdown(component.web_content_markdown)
context.sections[-1].elements.append(item)
if component.title:
component.element_id = frappe.scrub(component.title)
def add_css_class(self, context, item):
context.sections[-1].elements.append(component)
def add_css_class(self, context, component):
# add css class definitions selected by the user
if item.element_class and not item.hide:
css, is_dynamic = frappe.db.get_value('CSS Class', item.element_class, ['css', 'is_dynamic'])
if component.element_class and not component.hide:
css, is_dynamic = frappe.db.get_value('CSS Class', component.element_class, ['css', 'is_dynamic'])
if is_dynamic:
css = frappe.render_template(css, self.get_theme())
context.css_rules.append(css)
def add_color(self, component):
# convert to css color
if component.background_color and not component.hide:
component.background_color = frappe.db.get_value('Color',
component.background_color, 'color', cache=True)
def add_missing_semi(self, component):
if component.element_style and not component.element_style.strip().endswith(';'):
component.element_style = component.element_style.strip() + ';'
def render_content(self):
# webview can be rendered as an object (see footer)
return frappe.render_template("frappe/website/doctype/web_view/templates/web_view_content.html", self.get_context(self.as_dict()))
@ -72,3 +94,11 @@ class WebView(WebsiteGenerator):
title='Default Section',
elements=[]
))
def set_metatags(self, context):
context.metatags = {
"name": self.meta_title or context.title,
"description": self.meta_description,
"image": self.meta_image
}

View file

@ -8,11 +8,14 @@
"element_type",
"title",
"hide",
"contain_section_width",
"column_break_3",
"columns",
"background_color",
"element_class",
"element_style",
"section_break_5",
"web_view",
"section_type",
"web_content_type",
"web_content_html",
@ -26,33 +29,35 @@
"fieldtype": "Select",
"in_list_view": 1,
"label": "Element Type",
"options": "Section\nContent\nParagraph\nWeb List\nWeb Form",
"options": "Section\nContent\nImage\nWeb View",
"reqd": 1
},
{
"default": "List",
"depends_on": "eval:doc.element_type==='Section'",
"fieldname": "section_type",
"fieldtype": "Select",
"in_list_view": 1,
"label": "Section Type",
"options": "\nList\nTabbed\nGrid"
"options": "List\nTabbed\nGrid"
},
{
"default": "Markdown",
"depends_on": "eval:doc.element_type==='Content'",
"fieldname": "web_content_type",
"fieldtype": "Select",
"in_list_view": 1,
"label": "Web Content Type",
"options": "\nHTML\nMarkdown"
"options": "Markdown\nHTML"
},
{
"depends_on": "eval:doc.web_content_type==='HTML'",
"depends_on": "eval:doc.element_type === 'Content' && doc.web_content_type === 'HTML'",
"fieldname": "web_content_html",
"fieldtype": "HTML Editor",
"label": "Web Content HTML"
},
{
"depends_on": "eval:doc.web_content_type==='Markdown'",
"depends_on": "eval:doc.element_type === 'Content' && doc.web_content_type === 'Markdown'",
"fieldname": "web_content_markdown",
"fieldtype": "Markdown Editor",
"label": "Web Content Markdown"
@ -104,14 +109,34 @@
"fieldname": "element_style",
"fieldtype": "Small Text",
"label": "Element Style"
},
{
"default": "0",
"depends_on": "eval:doc.element_type==='Section'",
"fieldname": "contain_section_width",
"fieldtype": "Check",
"label": "Contain Section Width"
},
{
"fieldname": "background_color",
"fieldtype": "Link",
"label": "Background Color",
"options": "Color"
},
{
"depends_on": "eval:doc.element_type==='Web View'",
"fieldname": "web_view",
"fieldtype": "Link",
"label": "Web View",
"options": "Web View"
}
],
"istable": 1,
"links": [],
"modified": "2020-03-28 14:21:50.014823",
"modified": "2020-04-19 03:02:53.233036",
"modified_by": "Administrator",
"module": "Website",
"name": "Web View Item",
"name": "Web View Component",
"owner": "Administrator",
"permissions": [],
"quick_entry": 1,

View file

@ -0,0 +1,10 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2020, Frappe Technologies and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
# import frappe
from frappe.model.document import Document
class WebViewComponent(Document):
pass

View file

@ -14,8 +14,10 @@
"google_font",
"font_size",
"font_properties",
"use_full_width",
"column_break_7",
"button_rounded_corners",
"button_shadows",
"button_gradients",
"column_break_11",
"primary_color",
"text_color",
"light_color",
@ -99,29 +101,29 @@
"fieldtype": "Data",
"label": "Font Size"
},
{
"fieldname": "column_break_7",
"fieldtype": "Column Break"
},
{
"fieldname": "primary_color",
"fieldtype": "Color",
"label": "Primary Color"
"fieldtype": "Link",
"label": "Primary Color",
"options": "Color"
},
{
"fieldname": "text_color",
"fieldtype": "Color",
"label": "Text Color"
"fieldtype": "Link",
"label": "Text Color",
"options": "Color"
},
{
"fieldname": "dark_color",
"fieldtype": "Color",
"label": "Dark Color"
"fieldtype": "Link",
"label": "Dark Color",
"options": "Color"
},
{
"fieldname": "background_color",
"fieldtype": "Color",
"label": "Background Color"
"fieldtype": "Link",
"label": "Background Color",
"options": "Color"
},
{
"fieldname": "stylesheet_section",
@ -135,8 +137,9 @@
},
{
"fieldname": "light_color",
"fieldtype": "Color",
"label": "Light Color"
"fieldtype": "Link",
"label": "Light Color",
"options": "Color"
},
{
"default": "300,600",
@ -145,14 +148,30 @@
"label": "Font Properties"
},
{
"description": "Content will not be inside a \"container\" class, you will have to add your own containers for different sections.",
"fieldname": "use_full_width",
"fieldtype": "Data",
"label": "Use Full Width"
"default": "1",
"fieldname": "button_rounded_corners",
"fieldtype": "Check",
"label": "Button Rounded Corners"
},
{
"default": "0",
"fieldname": "button_shadows",
"fieldtype": "Check",
"label": "Button Shadows"
},
{
"default": "0",
"fieldname": "button_gradients",
"fieldtype": "Check",
"label": "Button Gradients"
},
{
"fieldname": "column_break_11",
"fieldtype": "Column Break"
}
],
"links": [],
"modified": "2020-03-19 09:46:48.750150",
"modified": "2020-04-19 05:18:49.820803",
"modified_by": "Administrator",
"module": "Website",
"name": "Website Theme",

View file

@ -1,21 +1,23 @@
{% if google_font %}
@import url('https://fonts.googleapis.com/css?family={{ google_font.replace(' ', '+') }}:{{ font_properties }}&display=swap');
$font-family-sans-serif: "{{ google_font }}", -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
{% endif %}
{% if primary_color %}$primary: {{ primary_color }};{% endif %}
{% if dark_color %}$dark: {{ dark_color }};{% endif %}
{% if text_color %}$body-color: {{ text_color }};{% endif %}
{% if background_color %}$body-bg: {{ background_color }};{% endif %}
{% endif -%}
$enable-shadows: {{ enable_shadows and "true" or "false" }};
$enable-gradients: {{ enable_gradients and "true" or "false" }};
$enable-rounded: {{ enable_rounded and "true" or "false" }};
{% if primary_color %}$primary: {{ frappe.db.get_value('Color', primary_color, 'color') }};{% endif -%}
{% if dark_color %}$dark: {{ frappe.db.get_value('Color', dark_color, 'color') }};{% endif -%}
{% if text_color %}$body-color: {{ frappe.db.get_value('Color', text_color, 'color') }};{% endif -%}
{% if background_color %}$body-bg: {{ frappe.db.get_value('Color', background_color, 'color') }};{% endif -%}
$enable-shadows: {{ button_shadows and "true" or "false" }};
$enable-gradients: {{ button_gradients and "true" or "false" }};
$enable-rounded: {{ button_rounded_corners and "true" or "false" }};
@import "frappe/public/scss/website";
{% if font_size -%}
body {
{% if font_size %}
font-size: {{ font_size }};
{% endif %}
}
{%- endif %}

View file

@ -1,26 +1,20 @@
{
"apply_style": 0,
"apply_text_styles": 0,
"creation": "2015-02-19 13:37:33.925909",
"css": ".navbar-header {\n display: none;\n}",
"custom": 0,
"docstatus": 0,
"doctype": "Website Theme",
"font_size": "14px",
"footer_color": "",
"footer_text_color": "",
"heading_style": "",
"heading_webfont": "",
"idx": 26,
"link_color": "",
"modified": "2016-12-29 05:40:17.289226",
"modified_by": "Administrator",
"module": "Website",
"name": "Standard",
"owner": "Administrator",
"text_color": "",
"text_webfont": "",
"theme": "Standard",
"top_bar_color": "",
"top_bar_text_color": ""
"button_gradients": 0,
"button_rounded_corners": 1,
"button_shadows": 0,
"creation": "2015-02-19 13:37:33.925909",
"custom": 0,
"docstatus": 0,
"doctype": "Website Theme",
"font_properties": "300,600",
"idx": 27,
"modified": "2020-04-19 05:34:56.086984",
"modified_by": "Administrator",
"module": "Website",
"name": "Standard",
"owner": "Administrator",
"primary_color": "Blue",
"theme": "Standard",
"theme_scss": "\n\n$primary: #5e3aa8;\n\n\n\n\n$enable-shadows: false;\n$enable-gradients: false;\n$enable-rounded: true;\n\n@import \"frappe/public/scss/website\";\n\nbody {\n \n}",
"theme_url": "/assets/css/standard_999ef15b.css"
}