소스 검색

Website Theme

version-14
Anand Doshi 10 년 전
부모
커밋
a1290bbdab
58개의 변경된 파일1714개의 추가작업 그리고 1100개의 파일을 삭제
  1. +5
    -0
      frappe/config/website.py
  2. +258
    -258
      frappe/core/doctype/docfield/docfield.json
  3. +1
    -1
      frappe/core/doctype/doctype/boilerplate/controller.py
  4. +1
    -1
      frappe/core/doctype/doctype/boilerplate/test_controller.py
  5. +2
    -1
      frappe/desk/search.py
  6. +2
    -1
      frappe/hooks.py
  7. +1
    -1
      frappe/model/sync.py
  8. +2
    -1
      frappe/modules/__init__.py
  9. +1
    -0
      frappe/patches.txt
  10. +56
    -0
      frappe/patches/v5_0/style_settings_to_website_theme.py
  11. +4
    -1
      frappe/print/doctype/print_format/print_format.py
  12. +0
    -1
      frappe/public/build.json
  13. +7
    -0
      frappe/public/css/form.css
  14. +1
    -1
      frappe/public/css/page.css
  15. +9
    -35
      frappe/public/css/website.css
  16. +6
    -11
      frappe/public/js/frappe/form/control.js
  17. +8
    -3
      frappe/public/js/frappe/form/formatters.js
  18. +4
    -6
      frappe/public/js/frappe/form/script_manager.js
  19. +1
    -1
      frappe/public/js/legacy/clientscriptAPI.js
  20. +60
    -50
      frappe/public/js/legacy/form.js
  21. +8
    -1
      frappe/public/less/form.less
  22. +1
    -1
      frappe/public/less/page.less
  23. +23
    -45
      frappe/public/less/website.less
  24. +2
    -1
      frappe/templates/base.html
  25. +5
    -1
      frappe/templates/generators/web_page.html
  26. +0
    -36
      frappe/templates/generators/website_group.html
  27. +1
    -1
      frappe/templates/includes/navbar.html
  28. +19
    -0
      frappe/templates/includes/website_theme/footer.css
  29. +69
    -0
      frappe/templates/includes/website_theme/navbar.css
  30. +1
    -1
      frappe/templates/pages/login.html
  31. +0
    -223
      frappe/templates/pages/style_settings.css
  32. +0
    -65
      frappe/templates/pages/style_settings.py
  33. +63
    -0
      frappe/templates/pages/website_theme.css
  34. +50
    -0
      frappe/templates/pages/website_theme.py
  35. +18
    -6
      frappe/utils/jinja.py
  36. +22
    -8
      frappe/website/context.py
  37. +2
    -2
      frappe/website/doctype/top_bar_item/top_bar_item.json
  38. +104
    -77
      frappe/website/doctype/web_page/web_page.json
  39. +10
    -4
      frappe/website/doctype/web_page/web_page.py
  40. +229
    -192
      frappe/website/doctype/website_settings/website_settings.json
  41. +3
    -0
      frappe/website/doctype/website_settings/website_settings.py
  42. +0
    -0
      frappe/website/doctype/website_theme/__init__.py
  43. +6
    -0
      frappe/website/doctype/website_theme/test_records.json
  44. +10
    -0
      frappe/website/doctype/website_theme/test_website_theme.py
  45. +27
    -0
      frappe/website/doctype/website_theme/website_theme.js
  46. +333
    -0
      frappe/website/doctype/website_theme/website_theme.json
  47. +54
    -0
      frappe/website/doctype/website_theme/website_theme.py
  48. +0
    -0
      frappe/website/doctype/website_theme_template/__init__.py
  49. +86
    -0
      frappe/website/doctype/website_theme_template/website_theme_template.json
  50. +9
    -0
      frappe/website/doctype/website_theme_template/website_theme_template.py
  51. +6
    -6
      frappe/website/js/website.js
  52. +0
    -14
      frappe/website/router.py
  53. +31
    -24
      frappe/website/template.py
  54. +74
    -16
      frappe/website/utils.py
  55. +3
    -3
      frappe/website/website_generator.py
  56. +0
    -0
      frappe/website/website_theme/__init__.py
  57. +0
    -0
      frappe/website/website_theme/standard/__init__.py
  58. +16
    -0
      frappe/website/website_theme/standard/standard.json

+ 5
- 0
frappe/config/website.py 파일 보기

@@ -72,6 +72,11 @@ def get_data():
"name": "Contact Us Settings",
"description": _("Settings for Contact Us Page."),
},
{
"type": "doctype",
"name": "Website Theme",
"description": _("List of themes for Website."),
},
{
"type": "doctype",
"name": "Social Login Keys",


+ 258
- 258
frappe/core/doctype/docfield/docfield.json 파일 보기

@@ -1,324 +1,324 @@
{
"allow_copy": 0,
"autoname": "hash",
"creation": "2013-02-22 01:27:33",
"docstatus": 0,
"doctype": "DocType",
"allow_copy": 0,
"autoname": "hash",
"creation": "2013-02-22 01:27:33",
"docstatus": 0,
"doctype": "DocType",
"fields": [
{
"fieldname": "label_and_type",
"fieldtype": "Section Break",
"label": "",
"fieldname": "label_and_type",
"fieldtype": "Section Break",
"label": "",
"permlevel": 0
},
},
{
"fieldname": "label",
"fieldtype": "Data",
"hidden": 0,
"in_list_view": 1,
"label": "Label",
"oldfieldname": "label",
"oldfieldtype": "Data",
"permlevel": 0,
"print_width": "163",
"reqd": 0,
"search_index": 1,
"fieldname": "label",
"fieldtype": "Data",
"hidden": 0,
"in_list_view": 1,
"label": "Label",
"oldfieldname": "label",
"oldfieldtype": "Data",
"permlevel": 0,
"print_width": "163",
"reqd": 0,
"search_index": 1,
"width": "163"
},
},
{
"default": "Data",
"fieldname": "fieldtype",
"fieldtype": "Select",
"hidden": 0,
"in_list_view": 1,
"label": "Type",
"oldfieldname": "fieldtype",
"oldfieldtype": "Select",
"options": "Attach\nButton\nCheck\nCode\nColumn Break\nCurrency\nData\nDate\nDatetime\nDynamic Link\nFloat\nFold\nHeading\nHTML\nImage\nInt\nLink\nLong Text\nPassword\nPercent\nRead Only\nSection Break\nSelect\nSmall Text\nTable\nText\nText Editor\nTime",
"permlevel": 0,
"reqd": 1,
"default": "Data",
"fieldname": "fieldtype",
"fieldtype": "Select",
"hidden": 0,
"in_list_view": 1,
"label": "Type",
"oldfieldname": "fieldtype",
"oldfieldtype": "Select",
"options": "Attach\nAttach Image\nButton\nCheck\nCode\nColumn Break\nCurrency\nData\nDate\nDatetime\nDynamic Link\nFloat\nFold\nHeading\nHTML\nImage\nInt\nLink\nLong Text\nPassword\nPercent\nRead Only\nSection Break\nSelect\nSmall Text\nTable\nText\nText Editor\nTime",
"permlevel": 0,
"reqd": 1,
"search_index": 1
},
},
{
"fieldname": "fieldname",
"fieldtype": "Data",
"hidden": 0,
"in_list_view": 1,
"label": "Name",
"oldfieldname": "fieldname",
"oldfieldtype": "Data",
"permlevel": 0,
"reqd": 0,
"fieldname": "fieldname",
"fieldtype": "Data",
"hidden": 0,
"in_list_view": 1,
"label": "Name",
"oldfieldname": "fieldname",
"oldfieldtype": "Data",
"permlevel": 0,
"reqd": 0,
"search_index": 1
},
},
{
"fieldname": "reqd",
"fieldtype": "Check",
"hidden": 0,
"in_list_view": 1,
"label": "Mandatory",
"oldfieldname": "reqd",
"oldfieldtype": "Check",
"permlevel": 0,
"print_width": "50px",
"reqd": 0,
"search_index": 0,
"fieldname": "reqd",
"fieldtype": "Check",
"hidden": 0,
"in_list_view": 1,
"label": "Mandatory",
"oldfieldname": "reqd",
"oldfieldtype": "Check",
"permlevel": 0,
"print_width": "50px",
"reqd": 0,
"search_index": 0,
"width": "50px"
},
},
{
"fieldname": "search_index",
"fieldtype": "Check",
"hidden": 0,
"label": "Index",
"oldfieldname": "search_index",
"oldfieldtype": "Check",
"permlevel": 0,
"print_width": "50px",
"reqd": 0,
"search_index": 0,
"fieldname": "search_index",
"fieldtype": "Check",
"hidden": 0,
"label": "Index",
"oldfieldname": "search_index",
"oldfieldtype": "Check",
"permlevel": 0,
"print_width": "50px",
"reqd": 0,
"search_index": 0,
"width": "50px"
},
},
{
"fieldname": "in_list_view",
"fieldtype": "Check",
"label": "In List View",
"permlevel": 0,
"print_width": "70px",
"fieldname": "in_list_view",
"fieldtype": "Check",
"label": "In List View",
"permlevel": 0,
"print_width": "70px",
"width": "70px"
},
},
{
"fieldname": "column_break_6",
"fieldtype": "Column Break",
"fieldname": "column_break_6",
"fieldtype": "Column Break",
"permlevel": 0
},
},
{
"depends_on": "eval:in_list([\"Float\", \"Currency\", \"Percent\"], doc.fieldtype)",
"description": "Set non-standard precision for a Float or Currency field",
"fieldname": "precision",
"fieldtype": "Select",
"label": "Precision",
"options": "\n1\n2\n3\n4\n5\n6\n7\n8\n9",
"permlevel": 0,
"depends_on": "eval:in_list([\"Float\", \"Currency\", \"Percent\"], doc.fieldtype)",
"description": "Set non-standard precision for a Float or Currency field",
"fieldname": "precision",
"fieldtype": "Select",
"label": "Precision",
"options": "\n1\n2\n3\n4\n5\n6\n7\n8\n9",
"permlevel": 0,
"print_hide": 1
},
},
{
"description": "For Links, enter the DocType as range\nFor Select, enter list of Options separated by comma",
"fieldname": "options",
"fieldtype": "Text",
"hidden": 0,
"in_list_view": 1,
"label": "Options",
"oldfieldname": "options",
"oldfieldtype": "Text",
"permlevel": 0,
"reqd": 0,
"description": "For Links, enter the DocType as range\nFor Select, enter list of Options separated by comma",
"fieldname": "options",
"fieldtype": "Text",
"hidden": 0,
"in_list_view": 1,
"label": "Options",
"oldfieldname": "options",
"oldfieldtype": "Text",
"permlevel": 0,
"reqd": 0,
"search_index": 0
},
},
{
"fieldname": "permissions",
"fieldtype": "Section Break",
"label": "Permissions",
"fieldname": "permissions",
"fieldtype": "Section Break",
"label": "Permissions",
"permlevel": 0
},
},
{
"fieldname": "depends_on",
"fieldtype": "Data",
"label": "Depends On",
"oldfieldname": "depends_on",
"oldfieldtype": "Data",
"fieldname": "depends_on",
"fieldtype": "Data",
"label": "Depends On",
"oldfieldname": "depends_on",
"oldfieldtype": "Data",
"permlevel": 0
},
},
{
"default": "0",
"fieldname": "permlevel",
"fieldtype": "Int",
"hidden": 0,
"label": "Perm Level",
"oldfieldname": "permlevel",
"oldfieldtype": "Int",
"permlevel": 0,
"print_width": "50px",
"reqd": 0,
"search_index": 0,
"default": "0",
"fieldname": "permlevel",
"fieldtype": "Int",
"hidden": 0,
"label": "Perm Level",
"oldfieldname": "permlevel",
"oldfieldtype": "Int",
"permlevel": 0,
"print_width": "50px",
"reqd": 0,
"search_index": 0,
"width": "50px"
},
},
{
"fieldname": "hidden",
"fieldtype": "Check",
"hidden": 0,
"label": "Hidden",
"oldfieldname": "hidden",
"oldfieldtype": "Check",
"permlevel": 0,
"print_width": "50px",
"reqd": 0,
"search_index": 0,
"fieldname": "hidden",
"fieldtype": "Check",
"hidden": 0,
"label": "Hidden",
"oldfieldname": "hidden",
"oldfieldtype": "Check",
"permlevel": 0,
"print_width": "50px",
"reqd": 0,
"search_index": 0,
"width": "50px"
},
},
{
"fieldname": "read_only",
"fieldtype": "Check",
"label": "Read Only",
"permlevel": 0,
"print_width": "50px",
"fieldname": "read_only",
"fieldtype": "Check",
"label": "Read Only",
"permlevel": 0,
"print_width": "50px",
"width": "50px"
},
},
{
"description": "Do not allow user to change after set the first time",
"fieldname": "set_only_once",
"fieldtype": "Check",
"label": "Set Only Once",
"description": "Do not allow user to change after set the first time",
"fieldname": "set_only_once",
"fieldtype": "Check",
"label": "Set Only Once",
"permlevel": 0
},
},
{
"fieldname": "column_break_13",
"fieldtype": "Column Break",
"fieldname": "column_break_13",
"fieldtype": "Column Break",
"permlevel": 0
},
},
{
"description": "User permissions should not apply for this Link",
"fieldname": "ignore_user_permissions",
"fieldtype": "Check",
"label": "Ignore User Permissions",
"description": "User permissions should not apply for this Link",
"fieldname": "ignore_user_permissions",
"fieldtype": "Check",
"label": "Ignore User Permissions",
"permlevel": 0
},
},
{
"fieldname": "allow_on_submit",
"fieldtype": "Check",
"label": "Allow on Submit",
"oldfieldname": "allow_on_submit",
"oldfieldtype": "Check",
"permlevel": 0,
"print_width": "50px",
"fieldname": "allow_on_submit",
"fieldtype": "Check",
"label": "Allow on Submit",
"oldfieldname": "allow_on_submit",
"oldfieldtype": "Check",
"permlevel": 0,
"print_width": "50px",
"width": "50px"
},
},
{
"fieldname": "report_hide",
"fieldtype": "Check",
"label": "Report Hide",
"oldfieldname": "report_hide",
"oldfieldtype": "Check",
"permlevel": 0,
"print_width": "50px",
"fieldname": "report_hide",
"fieldtype": "Check",
"label": "Report Hide",
"oldfieldname": "report_hide",
"oldfieldtype": "Check",
"permlevel": 0,
"print_width": "50px",
"width": "50px"
},
},
{
"fieldname": "display",
"fieldtype": "Section Break",
"label": "Display",
"fieldname": "display",
"fieldtype": "Section Break",
"label": "Display",
"permlevel": 0
},
},
{
"fieldname": "default",
"fieldtype": "Text",
"hidden": 0,
"label": "Default",
"oldfieldname": "default",
"oldfieldtype": "Text",
"permlevel": 0,
"reqd": 0,
"fieldname": "default",
"fieldtype": "Text",
"hidden": 0,
"label": "Default",
"oldfieldname": "default",
"oldfieldtype": "Text",
"permlevel": 0,
"reqd": 0,
"search_index": 0
},
},
{
"fieldname": "in_filter",
"fieldtype": "Check",
"label": "In Filter",
"oldfieldname": "in_filter",
"oldfieldtype": "Check",
"permlevel": 0,
"print_width": "50px",
"fieldname": "in_filter",
"fieldtype": "Check",
"label": "In Filter",
"oldfieldname": "in_filter",
"oldfieldtype": "Check",
"permlevel": 0,
"print_width": "50px",
"width": "50px"
},
},
{
"fieldname": "no_copy",
"fieldtype": "Check",
"label": "No Copy",
"oldfieldname": "no_copy",
"oldfieldtype": "Check",
"permlevel": 0,
"print_width": "50px",
"fieldname": "no_copy",
"fieldtype": "Check",
"label": "No Copy",
"oldfieldname": "no_copy",
"oldfieldtype": "Check",
"permlevel": 0,
"print_width": "50px",
"width": "50px"
},
},
{
"fieldname": "column_break_22",
"fieldtype": "Column Break",
"fieldname": "column_break_22",
"fieldtype": "Column Break",
"permlevel": 0
},
},
{
"fieldname": "description",
"fieldtype": "Text",
"in_list_view": 1,
"label": "Description",
"oldfieldname": "description",
"oldfieldtype": "Text",
"permlevel": 0,
"print_width": "300px",
"fieldname": "description",
"fieldtype": "Text",
"in_list_view": 1,
"label": "Description",
"oldfieldname": "description",
"oldfieldtype": "Text",
"permlevel": 0,
"print_width": "300px",
"width": "300px"
},
},
{
"fieldname": "print_hide",
"fieldtype": "Check",
"hidden": 0,
"label": "Print Hide",
"oldfieldname": "print_hide",
"oldfieldtype": "Check",
"permlevel": 0,
"print_width": "50px",
"reqd": 0,
"search_index": 0,
"fieldname": "print_hide",
"fieldtype": "Check",
"hidden": 0,
"label": "Print Hide",
"oldfieldname": "print_hide",
"oldfieldtype": "Check",
"permlevel": 0,
"print_width": "50px",
"reqd": 0,
"search_index": 0,
"width": "50px"
},
},
{
"fieldname": "print_width",
"fieldtype": "Data",
"label": "Print Width",
"fieldname": "print_width",
"fieldtype": "Data",
"label": "Print Width",
"permlevel": 0
},
},
{
"fieldname": "width",
"fieldtype": "Data",
"hidden": 0,
"label": "Width",
"oldfieldname": "width",
"oldfieldtype": "Data",
"permlevel": 0,
"print_width": "50px",
"reqd": 0,
"search_index": 0,
"fieldname": "width",
"fieldtype": "Data",
"hidden": 0,
"label": "Width",
"oldfieldname": "width",
"oldfieldtype": "Data",
"permlevel": 0,
"print_width": "50px",
"reqd": 0,
"search_index": 0,
"width": "50px"
},
},
{
"fieldname": "oldfieldname",
"fieldtype": "Data",
"hidden": 1,
"oldfieldname": "oldfieldname",
"oldfieldtype": "Data",
"permlevel": 0,
"reqd": 0,
"fieldname": "oldfieldname",
"fieldtype": "Data",
"hidden": 1,
"oldfieldname": "oldfieldname",
"oldfieldtype": "Data",
"permlevel": 0,
"reqd": 0,
"search_index": 0
},
},
{
"fieldname": "oldfieldtype",
"fieldtype": "Data",
"hidden": 1,
"oldfieldname": "oldfieldtype",
"oldfieldtype": "Data",
"permlevel": 0,
"reqd": 0,
"fieldname": "oldfieldtype",
"fieldtype": "Data",
"hidden": 1,
"oldfieldname": "oldfieldtype",
"oldfieldtype": "Data",
"permlevel": 0,
"reqd": 0,
"search_index": 0
}
],
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 1,
"in_dialog": 1,
"issingle": 0,
"istable": 1,
"modified": "2015-02-22 11:31:07.467882",
"modified_by": "Administrator",
"module": "Core",
"name": "DocField",
"owner": "Administrator",
"permissions": [],
],
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 1,
"in_dialog": 1,
"issingle": 0,
"istable": 1,
"modified": "2015-02-23 02:06:59.836515",
"modified_by": "Administrator",
"module": "Core",
"name": "DocField",
"owner": "Administrator",
"permissions": [],
"read_only": 0
}
}

+ 1
- 1
frappe/core/doctype/doctype/boilerplate/controller.py 파일 보기

@@ -1,4 +1,4 @@
# Copyright (c) 2013, {app_publisher} and contributors
# Copyright (c) 2015, {app_publisher} and contributors
# For license information, please see license.txt

from __future__ import unicode_literals


+ 1
- 1
frappe/core/doctype/doctype/boilerplate/test_controller.py 파일 보기

@@ -1,4 +1,4 @@
# Copyright (c) 2013, {app_publisher} and Contributors
# Copyright (c) 2015, {app_publisher} and Contributors
# See license.txt

import frappe


+ 2
- 1
frappe/desk/search.py 파일 보기

@@ -91,7 +91,8 @@ def search_widget(doctype, txt, query=None, searchfield=None, start=0,
def get_std_fields_list(meta, key):
# get additional search fields
sflist = meta.search_fields and meta.search_fields.split(",") or []
sflist = ['name'] + sflist
title_field = [meta.title_field] if (meta.title_field and meta.title_field not in sflist) else []
sflist = ['name'] + sflist + title_field
if not key in sflist:
sflist = sflist + [key]



+ 2
- 1
frappe/hooks.py 파일 보기

@@ -24,9 +24,10 @@ web_include_js = [
"website_script.js"
]

bootstrap = "assets/frappe/css/bootstrap.css"
web_include_css = [
"assets/css/frappe-web.css",
"style_settings.css"
"website_theme.css"
]

write_file_keys = ["file_url", "file_name"]


+ 1
- 1
frappe/model/sync.py 파일 보기

@@ -54,7 +54,7 @@ def sync_for(app_name, force=0, sync_everything = False, verbose=False):
def get_doc_files(files, start_path, force=0, sync_everything = False, verbose=False):
"""walk and sync all doctypes and pages"""

document_type = ['doctype', 'page', 'report', 'print_format']
document_type = ['doctype', 'page', 'report', 'print_format', 'website_theme']
for doctype in document_type:
doctype_path = os.path.join(start_path, doctype)
if os.path.exists(doctype_path):


+ 2
- 1
frappe/modules/__init__.py 파일 보기

@@ -10,7 +10,8 @@ import frappe.utils
from frappe import _

lower_case_files_for = ['DocType', 'Page', 'Report',
"Workflow", 'Module Def', 'Desktop Item', 'Workflow State', 'Workflow Action', 'Print Format']
"Workflow", 'Module Def', 'Desktop Item', 'Workflow State', 'Workflow Action', 'Print Format',
"Website Theme"]

def scrub(txt):
return frappe.scrub(txt)


+ 1
- 0
frappe/patches.txt 파일 보기

@@ -64,3 +64,4 @@ execute:frappe.db.sql("""update tabComment set comment = substr(comment, 6, loca
frappe.patches.v5_0.fix_feed
frappe.patches.v5_0.update_shared
frappe.patches.v5_0.bookmarks_to_stars
frappe.patches.v5_0.style_settings_to_website_theme

+ 56
- 0
frappe/patches/v5_0/style_settings_to_website_theme.py 파일 보기

@@ -0,0 +1,56 @@
from __future__ import unicode_literals
import frappe
from frappe import _

def execute():
frappe.reload_doc("website", "doctype", "website_theme")
frappe.reload_doc("website", "website_theme", "standard")
migrate_style_settings()
frappe.delete_doc("website", "doctype", "style_settings")

def migrate_style_settings():
style_settings = frappe.get_doc("Style Settings", "Style Settings")
standard_website_theme = frappe.get_doc("Website Theme", "Standard")

website_theme = frappe.copy_doc(standard_website_theme)
website_theme.custom = 1
website_theme.theme = _("Custom")

map_color_fields(style_settings, website_theme)
map_other_fields(style_settings, website_theme)

website_theme.save()
website_theme.use_theme()

def map_color_fields(style_settings, website_theme):
color_fields_map = {
"page_text": "text_color",
"page_links": "link_color",
"top_bar_background": "top_bar_color",
"top_bar_foreground": "top_bar_text_color",
"page_header_background": "page_header_color",
"page_header_color": "page_header_text_color",
"footer_background": "footer_color",
"footer_color": "footer_text_color",
}

for from_fieldname, to_fieldname in color_fields_map.items():
from_value = style_settings.get(from_fieldname)

if from_value:
website_theme.set(to_fieldname, "#{0}".format(from_value))

def map_other_fields(style_settings, website_theme):
other_fields_map = {
"heading_text_as": "heading_style",
"google_web_font_for_heading": "heading_webfont",
"google_web_font_for_text": "text_webfont",
"add_css": "css"
}

for from_fieldname, to_fieldname in other_fields_map.items():
website_theme.set(to_fieldname, style_settings.get(from_fieldname))

for fieldname in ("apply_style", "background_image", "background_color",
"font_size"):
website_theme.set(fieldname, style_settings.get(fieldname))

+ 4
- 1
frappe/print/doctype/print_format/print_format.py 파일 보기

@@ -10,7 +10,10 @@ from frappe.model.document import Document

class PrintFormat(Document):
def validate(self):
if self.standard=="Yes" and frappe.session.user != "Administrator":
if (self.standard=="Yes"
and not frappe.local.conf.get("developer_mode")
and not (frappe.flags.in_import or frappe.flags.in_test)):

frappe.throw(frappe._("Standard Print Format cannot be updated"))

# old_doc_type is required for clearing item cache


+ 0
- 1
frappe/public/build.json 파일 보기

@@ -1,6 +1,5 @@
{
"css/frappe-web.css": [
"public/css/bootstrap.css",
"public/css/font-awesome.css",
"public/css/nprogress.css",
"public/css/website.css"


+ 7
- 0
frappe/public/css/form.css 파일 보기

@@ -14,6 +14,7 @@
.form-inner-toolbar {
padding: 10px 15px;
background-color: #fafbfc;
border-bottom: 1px dashed #d1d8dd;
text-align: right;
}
.form-clickable-section {
@@ -139,3 +140,9 @@
.attach-image-display {
cursor: pointer;
}
@media (min-width: 768px) {
.form-column.col-sm-12 > form > .input-max-width {
max-width: 50%;
padding-right: 15px;
}
}

+ 1
- 1
frappe/public/css/page.css 파일 보기

@@ -10,7 +10,7 @@
top: 41px;
margin: auto;
background-color: #fff;
z-index: 2;
z-index: 101;
}
.sub-heading {
display: inline-block;


+ 9
- 35
frappe/public/css/website.css 파일 보기

@@ -41,6 +41,11 @@ img {
.navbar-bg {
background-color: #f5f7fa;
}
.navbar {
box-shadow: none;
border-radius: 0px;
margin-bottom: 0px;
}
.social-icons i {
font-size: 120%;
}
@@ -54,7 +59,6 @@ img {
margin-left: 5px;
}
.web-footer {
border-top: 1px solid #d1d8dd;
padding: 20px 0px;
min-height: 140px;
}
@@ -157,28 +161,6 @@ img {
.border-bottom {
border-bottom: 1px solid #d1d8dd;
}
.navbar {
box-shadow: none;
border-radius: 0px;
margin-bottom: 0px;
padding-top: 15px;
padding-bottom: 15px;
border-bottom: 1px solid #d1d8dd;
}
.navbar-brand {
padding-right: 30px;
max-width: 80%;
min-height: 20px;
height: auto;
}
.navbar a.active {
font-weight: bold;
}
@media (min-width: 768px) {
.navbar-brand {
max-width: 300px;
}
}
.panel-container {
margin-top: 35px;
}
@@ -258,13 +240,8 @@ body {
/* The html and body elements cannot have any padding or margin. */
}
.page-footer {
margin: 20px 0px 0px;
padding: 15px 0px;
border-top: 1px solid #eee;
}
/* website group */
.view-selector {
margin-bottom: 15px;
border-top: 1px solid #d1d8dd;
}
/* post and post list */
.web-list-item {
@@ -273,9 +250,6 @@ body {
margin-right: -30px;
padding-right: 30px;
}
.web-list-item:last-child {
border-bottom: none;
}
.web-list-item h3 {
margin: 0 0 5px 0;
}
@@ -283,6 +257,9 @@ body {
color: inherit !important;
text-decoration: none;
}
.web-list-item:last-child {
border-bottom: none;
}
textarea {
resize: vertical;
}
@@ -298,9 +275,6 @@ textarea {
display: inline-block !important;
}
}
.nav-tabs > li > a {
padding: 7px 10px;
}
.btn-more {
margin-top: 15px;
}


+ 6
- 11
frappe/public/js/frappe/form/control.js 파일 보기

@@ -128,21 +128,16 @@ frappe.ui.form.ControlImage = frappe.ui.form.Control.extend({
make: function() {
this._super();
var me = this;
this.$wrapper = $("<div></div>")
.appendTo(this.parent)
.css({"max-width": "600px", "margin": "0px"});
this.$wrapper.css({"margin": "0px"});
this.$body = $("<div></div>").appendTo(this.$wrapper)
.css({"margin-bottom": "10px", "max-width": "100%"})

.css({"margin-bottom": "10px"})
this.$wrapper.on("refresh", function() {
var doc = null;
me.$body.empty();

if(me.docname) {
var doc = frappe.model.get_doc(me.doctype, me.docname);
}
var doc = me.get_doc();
if(doc && me.df.options && doc[me.df.options]) {
me.$img = $("<img src='"+doc[me.df.options]+"' style='max-width: 100%;'>")
me.$img = $("<img src='"+doc[me.df.options]+"' class='img-responsive'>")
.appendTo(me.$body);
} else {
me.$buffer = $("<div class='missing-image'><i class='octicon octicon-circle-slash'></i></div>")
@@ -155,7 +150,7 @@ frappe.ui.form.ControlImage = frappe.ui.form.Control.extend({
});

frappe.ui.form.ControlInput = frappe.ui.form.Control.extend({
// horizontal: true,
horizontal: true,
make: function() {
// parent element
this._super();
@@ -194,7 +189,7 @@ frappe.ui.form.ControlInput = frappe.ui.form.Control.extend({
},
set_max_width: function() {
if(this.horizontal) {
this.$wrapper.css({"max-width": "600px"});
this.$wrapper.addClass("input-max-width");
}
},



+ 8
- 3
frappe/public/js/frappe/form/formatters.js 파일 보기

@@ -94,7 +94,7 @@ frappe.form.formatters = {
}

if(!match) {
return replace_newlines(value);
value = replace_newlines(value);
}
}

@@ -139,7 +139,7 @@ frappe.form.formatters = {
return frappe.form.formatters.Text(value);
},
TextEditor: function(value) {
return frappe.form.formatters.Text(frappe.utils.remove_script_and_style(value));
return frappe.form.formatters.Text(value);
},
Code: function(value) {
return "<pre>" + (value==null ? "" : $("<div>").text(value).html()) + "</pre>"
@@ -179,7 +179,12 @@ frappe.format = function(value, df, options, doc) {

formatter = df.formatter || frappe.form.get_formatter(fieldtype);

return formatter(value, df, options, doc);
var formatted = formatter(value, df, options, doc);

if (typeof formatted == "string")
formatted = frappe.utils.remove_script_and_style(formatted);

return formatted;
}

frappe.get_format_helper = function(doc) {


+ 4
- 6
frappe/public/js/frappe/form/script_manager.js 파일 보기

@@ -31,23 +31,21 @@ frappe.ui.form.ScriptManager = Class.extend({
handlers = this.get_handlers(event_name, doctype, name, callback);
if(callback) handlers.push(callback);

$.each(handlers, function(i, fn) {
fn();
})
return $.when.apply($, $.map(handlers, function(fn) { return fn(); }));
},
get_handlers: function(event_name, doctype, name, callback) {
var handlers = [];
var me = this;
if(frappe.ui.form.handlers[doctype] && frappe.ui.form.handlers[doctype][event_name]) {
$.each(frappe.ui.form.handlers[doctype][event_name], function(i, fn) {
handlers.push(function() { fn(me.frm, doctype, name) });
handlers.push(function() { return fn(me.frm, doctype, name) });
});
}
if(this.frm.cscript[event_name]) {
handlers.push(function() { me.frm.cscript[event_name](me.frm.doc, doctype, name); });
handlers.push(function() { return me.frm.cscript[event_name](me.frm.doc, doctype, name); });
}
if(this.frm.cscript["custom_" + event_name]) {
handlers.push(function() { me.frm.cscript["custom_" + event_name](me.frm.doc, doctype, name); });
handlers.push(function() { return me.frm.cscript["custom_" + event_name](me.frm.doc, doctype, name); });
}
return handlers;
},


+ 1
- 1
frappe/public/js/legacy/clientscriptAPI.js 파일 보기

@@ -289,7 +289,7 @@ _f.Frm.prototype.new_doc = function(doctype, field, opts) {
_f.Frm.prototype.set_read_only = function() {
var perm = [];
var docperms = frappe.perm.get_perm(cur_frm.doc.doctype);
for (var i=0, l=docperms.lenght; i<l; i++) {
for (var i=0, l=docperms.length; i<l; i++) {
var p = docperms[i];
perm[p.permlevel || 0] = {read:1};
}


+ 60
- 50
frappe/public/js/legacy/form.js 파일 보기

@@ -126,26 +126,29 @@ _f.Frm.prototype.setup_drag_drop = function() {
var me = this;
$(this.wrapper).on('dragenter dragover', false)
.on('drop', function (e) {
var dataTransfer = e.originalEvent.dataTransfer;
if (!(dataTransfer && dataTransfer.files && dataTransfer.files.length > 0)) {
return;
}

e.stopPropagation();
e.preventDefault();

if(me.doc.__islocal) {
msgprint(__("Please save before attaching."));
return false;
throw "attach error";
}

if(me.attachments.max_reached()) {
msgprint(__("Maximum Attachment Limit for this record reached."));
throw "attach error";
}

var dataTransfer = e.originalEvent.dataTransfer;
if (dataTransfer && dataTransfer.files && dataTransfer.files.length > 0) {
frappe.upload.upload_file(dataTransfer.files[0], me.attachments.get_args(), {
callback: function(attachment, r) {
me.attachments.attachment_uploaded(attachment, r);
}
});
}
frappe.upload.upload_file(dataTransfer.files[0], me.attachments.get_args(), {
callback: function(attachment, r) {
me.attachments.attachment_uploaded(attachment, r);
}
});
});
}

@@ -570,19 +573,6 @@ _f.Frm.prototype._save = function(save_action, callback, btn, on_error) {
if((!this.meta.in_dialog || this.in_form) && !this.meta.istable)
scroll(0, 0);

if(save_action != "Update") {
// validate
validated = true;
this.script_manager.trigger("validate");
this.script_manager.trigger("before_save");

if(!validated) {
if(on_error)
on_error();
return;
}
}

var after_save = function(r) {
if(!r.exc) {
me.script_manager.trigger("after_save");
@@ -603,7 +593,25 @@ _f.Frm.prototype._save = function(save_action, callback, btn, on_error) {
}
}

frappe.ui.form.save(me, save_action, after_save, btn);
if(save_action != "Update") {
// validate
validated = true;
$.when(this.script_manager.trigger("validate"), this.script_manager.trigger("before_save"))
.done(function() {
// done is called after all ajaxes in validate & before_save are completed :)

if(!validated) {
if(on_error)
on_error();
return;
}

frappe.ui.form.save(me, save_action, after_save, btn);
});

} else {
frappe.ui.form.save(me, save_action, after_save, btn);
}
}


@@ -612,19 +620,20 @@ _f.Frm.prototype.savesubmit = function(btn, callback, on_error) {
this.validate_form_action("Submit");
frappe.confirm(__("Permanently Submit {0}?", [this.docname]), function() {
validated = true;
me.script_manager.trigger("before_submit");
if(!validated) {
if(on_error)
on_error();
return;
}

me.save('Submit', function(r) {
if(!r.exc) {
callback && callback();
me.script_manager.trigger("on_submit");
me.script_manager.trigger("before_submit").done(function() {
if(!validated) {
if(on_error)
on_error();
return;
}
}, btn, on_error);

me.save('Submit', function(r) {
if(!r.exc) {
callback && callback();
me.script_manager.trigger("on_submit");
}
}, btn, on_error);
});
});
};

@@ -633,23 +642,24 @@ _f.Frm.prototype.savecancel = function(btn, callback, on_error) {
this.validate_form_action('Cancel');
frappe.confirm(__("Permanently Cancel {0}?", [this.docname]), function() {
validated = true;
me.script_manager.trigger("before_cancel");
if(!validated) {
if(on_error)
on_error();
return;
}
me.script_manager.trigger("before_cancel").done(function() {
if(!validated) {
if(on_error)
on_error();
return;
}

var after_cancel = function(r) {
if(!r.exc) {
me.refresh();
callback && callback();
me.script_manager.trigger("after_cancel");
} else {
on_error();
var after_cancel = function(r) {
if(!r.exc) {
me.refresh();
callback && callback();
me.script_manager.trigger("after_cancel");
} else {
on_error();
}
}
}
frappe.ui.form.save(me, "cancel", after_cancel, btn);
frappe.ui.form.save(me, "cancel", after_cancel, btn);
});
});
}



+ 8
- 1
frappe/public/less/form.less 파일 보기

@@ -19,7 +19,7 @@
.form-inner-toolbar {
padding: 10px 15px;
background-color: @light-bg;
//border-bottom: 1px solid @border-color;
border-bottom: 1px dashed @border-color;
text-align: right;
}

@@ -179,3 +179,10 @@
.attach-image-display {
cursor: pointer;
}

@media (min-width: 768px) {
.form-column.col-sm-12 > form > .input-max-width {
max-width: 50%;
padding-right: 15px;
}
}

+ 1
- 1
frappe/public/less/page.less 파일 보기

@@ -14,7 +14,7 @@
top: 41px;
margin: auto;
background-color: #fff;
z-index: 2;
z-index: 101;
}

.sub-heading {


+ 23
- 45
frappe/public/less/website.less 파일 보기

@@ -13,6 +13,7 @@
a {
cursor: pointer;
}

a, a:hover, a:active, a:focus {
outline: 0;
}
@@ -54,6 +55,12 @@ img {
background-color: @navbar-bg;
}

.navbar {
box-shadow: none;
border-radius: 0px;
margin-bottom: 0px;
}

.social-icons i {
font-size: 120%;
}
@@ -69,7 +76,6 @@ img {
}

.web-footer {
border-top: 1px solid @border-color;
padding: 20px 0px;
min-height: 140px;
}
@@ -184,32 +190,6 @@ img {
border-bottom: 1px solid @border-color;
}

.navbar {
box-shadow: none;
border-radius: 0px;
margin-bottom: 0px;
padding-top: 15px;
padding-bottom: 15px;
border-bottom: 1px solid @border-color;
}

.navbar-brand {
padding-right: 30px;
max-width: 80%;
min-height: 20px;
height: auto;
}

.navbar a.active {
font-weight: bold;
}

@media (min-width: 768px) {
.navbar-brand {
max-width: 300px;
}
}

.panel-container {
margin-top: 35px;
}
@@ -257,9 +237,11 @@ fieldset {
.page-content {
padding-bottom: 30px;
}

div[data-html-block="content"] {
padding-right: 15px;
}

.page-content hr {
margin-left: -15px;
margin-right: -30px;
@@ -272,6 +254,7 @@ div[data-html-block="content"] {
border-left: 1px solid @border-color;
padding-left: 15px;
}

.sidebar-item {
margin: 0px;
padding: 5px 0px;
@@ -279,6 +262,7 @@ div[data-html-block="content"] {
color: @text-muted;
font-size: 12px;
}

.sidebar-item:first-child {
padding-top: 10px;
}
@@ -302,17 +286,11 @@ body {
}

.page-footer {
margin: 20px 0px 0px;
padding: 15px 0px;
border-top: 1px solid #eee;
border-top: 1px solid @border-color;
}


/* website group */
.view-selector {
margin-bottom: 15px;
}

/* post and post list */

.web-list-item {
@@ -320,17 +298,20 @@ body {
border-bottom: 1px solid @border-color;
margin-right: -30px;
padding-right: 30px;

h3 {
margin: 0 0 5px 0;

a {
color: inherit !important;
text-decoration: none;
}
}
}

.web-list-item:last-child {
border-bottom: none;
}
.web-list-item h3 {
margin: 0 0 5px 0;
}
.web-list-item h3 a {
color: inherit !important;
text-decoration: none;
}

textarea {
resize: vertical;
@@ -351,10 +332,6 @@ textarea {
}
}

.nav-tabs > li > a {
padding: 7px 10px;
}

.btn-more {
margin-top: 15px;
}
@@ -457,3 +434,4 @@ a.text-extra-muted:focus {
color: inherit;
border-bottom: 1px solid @text-muted;
}


+ 2
- 1
frappe/templates/base.html 파일 보기

@@ -23,6 +23,8 @@ Built on Frappe.io. Free and Open Source Framework for the Web. https://frappe.i
{{ meta_block }}
{% endif %}

<link type="text/css" rel="stylesheet" href="{{ bootstrap }}">

{%- for link in web_include_css %}
<link type="text/css" rel="stylesheet" href="{{ link }}">
{%- endfor -%}
@@ -59,7 +61,6 @@ Built on Frappe.io. Free and Open Source Framework for the Web. https://frappe.i
{%- block sidebar -%}
{%- if sidebar is defined -%}
{{ sidebar }}
{{ private_pages or "" }}
{%- endif -%}
{%- endblock -%}
</div>


+ 5
- 1
frappe/templates/generators/web_page.html 파일 보기

@@ -1,7 +1,11 @@
{% if header -%}
{%- block header -%} {{ header }} {%- endblock -%}
{%- endif %}

{% block content %}
<div class="webpage-content">
{% include "templates/includes/slideshow.html" %}
<article class="web-page-content" id="{{ name }}">
<article class="web-page-content" id="{{ name }}" {% if text_align -%}style="text-align: {{ text_align }}"{%- endif %}>
{{ main_section or "" }}
</article>
{% if enable_comments -%}


+ 0
- 36
frappe/templates/generators/website_group.html 파일 보기

@@ -1,36 +0,0 @@
{% block header %}{{ group.group_title }}{% endblock %}

{% block content %}
{%- if group.group_description -%}
<p class="lead">{{ group.group_description }}</p>
{%- endif -%}

<ul class="nav nav-tabs view-selector">
{%- for t in views -%}
{% set url = (pathname if t.default else "{}?view={}".format(pathname, t.name)) %}
<li class="{% if view.name==t.name -%} active {%- endif %} {% if t.hidden -%} hide {%- endif %}"
data-view="{{ t.name }}">
<a href="{{ url or '' }}"><i class="{{ t.icon }}"></i>
<span class="nav-label">{{ t.label }}</span></a>
</li>
{%- endfor -%}
</ul>

<script>
{%- if access -%}
website.access = {{ access|json }};
{%- endif -%}
website.group = "{{ group.name }}";
website.view = "{{ view.name }}";
website.upvote = {{ 1 if view.upvote else 0 }};
{% if view.upvote %}
website.setup_upvote();
{% endif %}
</script>

{% include view.template_path %}

<script>$(function() { website.toggle_upvote(); });</script>

{% endblock %}

+ 1
- 1
frappe/templates/includes/navbar.html 파일 보기

@@ -1,5 +1,5 @@
<header>
<nav class="navbar navbar-main" role="navigation">
<nav class="navbar navbar-default navbar-main" role="navigation">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse"


+ 19
- 0
frappe/templates/includes/website_theme/footer.css 파일 보기

@@ -0,0 +1,19 @@
.web-footer {
background-color: {{ theme.footer_color }};
border-top: 1px solid {{ get_shade(theme.footer_color, 10) }};
}

.web-footer,
.web-footer a {
color: {{ theme.footer_text_color }};
}

.web-footer a:hover,
.web-footer a:focus,
.web-footer a:active {
color: {{ get_shade(theme.footer_text_color, 5) }};
}

.web-footer input {
border: 1px solid {{ get_shade(theme.footer_color, 10) }};
}

+ 69
- 0
frappe/templates/includes/website_theme/navbar.css 파일 보기

@@ -0,0 +1,69 @@
.navbar {
background-color: {{ theme.top_bar_color }};
background-repeat: repeat-x;
background-image: none;
border: none;
border-bottom: 1px solid {{ get_shade(theme.top_bar_color, 10) }};
}

.navbar .navbar-text,
.navbar .navbar-brand,
.navbar .navbar-link,
.navbar .nav > li > a {
color: {{ theme.top_bar_text_color }};
text-shadow: none;
padding-top: 25px;
padding-bottom: 25px;
}

{# links #}
.navbar .navbar-brand:hover,
.navbar .navbar-brand:focus,
.navbar .navbar-brand:active,
.navbar .nav .active > a,
.navbar .nav .active > a:hover,
.navbar .nav .active > a:focus,
.navbar .nav .active > a:active,
.navbar .navbar-link:hover,
.navbar .navbar-link:focus,
.navbar .navbar-link:active,
.navbar .nav > li > a:hover,
.navbar .nav > li > a:focus,
.navbar .nav > li > a:active {
color: {{ get_shade(theme.top_bar_text_color, 15) }};
background-color: transparent;
-webkit-box-shadow: none;
-moz-box-shadow: none;
box-shadow: none;
}

.navbar-fixed-top,
.navbar-static-top {
-webkit-box-shadow: none;
-moz-box-shadow: none;
box-shadow: none;

}

.navbar-toggle {
margin-top: 7px;
margin-bottom: 7px;
}

.navbar-collapse {
border-radius: 0px;
}

{# navbar brand #}
.navbar-brand {
padding-right: 30px;
max-width: 80%;
min-height: 20px;
height: auto;
}

@media (min-width: 768px) {
.navbar-brand {
max-width: 300px;
}
}

+ 1
- 1
frappe/templates/pages/login.html 파일 보기

@@ -1,6 +1,7 @@
{% block style %}{% include "templates/includes/login.css" %}{% endblock %}

{% block content %}
<!-- no-header -->
<div class="login-content container" style="max-width: 800px; padding-top: 30px;">
<form class="form-signin form-login" role="form">
{%- if social_login -%}
@@ -66,7 +67,6 @@
</p>

</form>

</div>
{% endblock %}



+ 0
- 223
frappe/templates/pages/style_settings.css 파일 보기

@@ -1,223 +0,0 @@
{% if doc.apply_style %}
{% if doc.at_import %}
{{ doc.at_import }}
{% endif %}

{% set border_color = border_color %}

body {
{% if doc.background_image %}
background: url("{{ doc.background_image }}") repeat;
{% elif doc.background_color %}
background-color: #{{ doc.background_color }};
background-image: none;
{% else %}
background-color: #ffffff;
{% endif %}
{% if doc.font or doc.google_web_font_for_text %}
font-family: '{{ doc.google_web_font_for_text or doc.font }}', 'Helvetica Neue', Arial, Sans !important;
{% endif %}
{% if doc.font_size %}font-size: {{ doc.font_size }} !important;{% endif %}
{% if doc.page_text %}color: #{{ doc.page_text }};{% endif %}
}

{% if doc.page_links %}a, a:hover {
color: #{{ doc.page_links }};
}{% endif %}

{% if doc.font_size %}
.small {
font-size: {{ doc.small_font_size }} !important;
}
{% endif %}

{% if doc.google_web_font_for_heading or doc.heading_font %}h1, h2, h3, h4, h5 {
font-family: '{{ doc.google_web_font_for_heading or doc.heading_font }}', 'Helvetica Neue', Arial !important;
}{% endif %}

{% if doc.heading_text_style %}h1, h2, h3, h4, h5 {
text-transform: {{ doc.heading_text_style }};
}{% endif %}

{% if doc.footer_color -%}
.web-footer, .web-footer a {
color: #{{ doc.footer_color }} !important;
}
{% endif -%}
{% if doc.footer_background -%}
.web-footer {
background-color: #{{ doc.footer_background }};
}
{% endif -%}

/* Bootstrap Navbar */
.navbar-default {
border: 0px;
}

.navbar {
background-color: #{{ doc.top_bar_background}};
background-repeat: repeat-x;
background-image: none;
}

.navbar .navbar-brand,
.navbar .navbar-brand:hover,
.navbar .navbar-brand:focus,
.navbar .nav > li > a {
color: #{{ doc.top_bar_foreground }};
text-shadow: none;
}

.navbar .nav > li > a:hover,
.navbar .nav > li > a:focus {
color: #{{ doc.top_bar_foreground }};
background-color: transparent;
}

.navbar .navbar-text {
color: #{{ doc.top_bar_foreground}};
}

.navbar {
border-bottom: 1px solid #{{ border_color }};
}

.navbar .nav .active > a,
.navbar .nav .active > a:hover,
.navbar .nav .active > a:focus {
color: #{{ doc.top_bar_foreground }};
background-color: transparent;
}

.navbar .navbar-link {
color: #444444;
}

.navbar .navbar-link:hover,
.navbar .navbar-link:focus {
color: #{{ doc.top_bar_foreground}};
}

.navbar-fixed-top,
.navbar-static-top {
-webkit-box-shadow: none;
-moz-box-shadow: none;
box-shadow: none;

}
.navbar .nav > .active > a,
.navbar .nav > .active > a:hover,
.navbar .nav > .active > a:focus {
color: #424242;
text-decoration: none;
background-color: transparent;
-webkit-box-shadow: none;
-moz-box-shadow: none;
box-shadow: none;
}

.navbar .nav li.dropdown > .dropdown-toggle .caret,
.navbar .nav li.dropdown > .dropdown-toggle:hover .caret {
border-top-color: #{{ doc.top_bar_foreground}};
border-bottom-color: #{{ doc.top_bar_foreground}};
}

.navbar .nav li.dropdown.open > .dropdown-toggle .caret,
.navbar .nav li.dropdown.open > .dropdown-toggle:hover .caret {
border-top-color: #{{ doc.top_bar_background}};
border-bottom-color: #{{ doc.top_bar_background}};
}

.navbar .nav li.dropdown.open > .dropdown-toggle {
color: #{{ doc.top_bar_background}};
background-color: #{{ doc.top_bar_foreground}};
}

@media (max-width: 800px) {
.navbar .nav-collapse .nav > li > a,
.navbar .nav-collapse .dropdown-menu a {
background-color: #{{ doc.top_bar_background}};
color: #{{ doc.top_bar_foreground}};
}
.navbar .nav-collapse .nav > li > a:hover,
.navbar .nav-collapse .dropdown-menu a:hover {
background-color: #{{ doc.top_bar_foreground}};
color: #{{ doc.top_bar_background}};
}

.navbar .nav li.dropdown > .dropdown-toggle .caret {
border-top-color: #{{ doc.top_bar_foreground }};
border-bottom-color: #{{ doc.top_bar_foreground }};
}

.navbar .nav li.dropdown > .dropdown-toggle:hover .caret {
border-top-color: #{{ doc.top_bar_foreground }};
border-bottom-color: #{{ doc.top_bar_foreground }};
}

.navbar .nav li.dropdown.open > .dropdown-toggle .caret,
.navbar .nav li.dropdown.open > .dropdown-toggle:hover .caret {
border-top-color: #{{ doc.top_bar_background }};
border-bottom-color: #{{ doc.top_bar_background }};
}

}

.navbar-default .navbar-toggle .icon-bar {
background-color: #{{ doc.top_bar_foreground }};
}

.breadcrumb {
background-color: #{{ doc.background_color | get_hex_shade(5) }};
}

.breadcrumb > li {
text-shadow: none;
}


.table-striped tbody > tr:nth-child(odd) > td,
.table-striped tbody > tr:nth-child(odd) > th {
background-color: #{{ doc.background_color | get_hex_shade(5) }};
}

.table-hover tbody tr:hover td,
.table-hover tbody tr:hover th {
background-color: #{{ doc.background_color | get_hex_shade(10) }};
}

.table-bordered {
border: 1px solid #{{ border_color }};
}

.table th,
.table td {
border-top: 1px solid #{{ border_color }};
}

.table-bordered th,
.table-bordered td {
border-left: 1px solid #{{ border_color }};
}



.hero-unit {
background-color: #{{ border_color }};
}

pre, code {
background-color: #{{ doc.background_color | get_hex_shade(5) }};
}

hr {
border-top: 1px solid #{{ border_color }};
border-bottom: 1px solid #{{ doc.background_color | get_hex_shade(5) }};
}

{% if doc.add_css -%}
/* User CSS */
{{ doc.add_css }}
{%- endif %}
{% endif %}

+ 0
- 65
frappe/templates/pages/style_settings.py 파일 보기

@@ -1,65 +0,0 @@
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
# MIT License. See license.txt

from __future__ import unicode_literals
import frappe

no_sitemap = 1
base_template_path = "templates/pages/style_settings.css"

default_properties = {
"background_color": "FFFFFF",
"top_bar_background": "FFFFFF",
"top_bar_foreground": "000000",
"page_text": "000000",
"page_header_background": "263248",
"page_header_color": "ffffff",
"font_size": "14px"
}


def get_context(context):
"""returns web style"""
doc = frappe.get_doc("Style Settings", "Style Settings")
prepare(doc)

return { "doc": doc }

def prepare(doc):
from frappe.utils import cint, cstr

for d in default_properties:
if not doc.get(d):
doc.set(d, default_properties[d])

if not doc.font_size:
doc.font_size = "14px"

doc.small_font_size = cstr(cint(doc.font_size[:-2])-2) + 'px'

fonts = []
if doc.google_web_font_for_heading:
fonts.append(doc.google_web_font_for_heading)
if doc.google_web_font_for_text:
fonts.append(doc.google_web_font_for_text)

fonts = list(set(fonts))

if doc.heading_text_as:
doc.heading_text_style = {
"UPPERCASE": "uppercase",
"Title Case":"capitalize",
"lowercase": "lowercase"
}.get(doc.heading_text_as) or ""

doc.at_import = ""
for f in fonts:
doc.at_import += "\n@import url(https://fonts.googleapis.com/css?family=%s:400,700);" % f.replace(" ", "+")

# move @import from add_css field to the top of the css file
if doc.add_css and "@import url" in doc.add_css:
import re
at_imports = list(set(re.findall("@import url\([^\(\)]*\);", doc.add_css)))
doc.at_import += "\n" + "\n".join(at_imports)
for imp in at_imports:
doc.add_css = doc.add_css.replace(imp, "")

+ 63
- 0
frappe/templates/pages/website_theme.css 파일 보기

@@ -0,0 +1,63 @@
{%- if theme and theme.apply_style -%}

{%- set font_family_sans_serif = '"Helvetica Neue", Helvetica, Arial, sans-serif' -%}

{%- set heading_selectors = "h1, h2, h3, h4, h5, h6" -%}

{{ theme.webfont_import or "" }}

body {
{# background #}
{% if theme.background_image -%}
background: url("{{ theme.background_image }}") repeat;

{%- else -%}
background-color: {{ theme.background_color }};
background-image: none;

{%- endif %}

{# text #}
{% if theme.text_webfont -%}
font-family: "{{ theme.text_webfont }}", {{ font_family_sans_serif }};

{%- endif %}

{% if theme.font_size -%}
font-size: {{ theme.font_size }};
{%- endif %}

color: {{ theme.text_color }};
}

{# links #}
a {
color: {{ theme.link_color }};
}

a:hover,
a:focus,
a:active {
color: {{ get_shade(theme.link_color, 5) }};
}

{# headings #}
{% if theme.heading_webfont -%}
{{ heading_selectors }} {
font-family: "{{ theme.heading_webfont }}", {{ font_family_sans_serif }};
}
{%- endif %}

{% if theme.heading_style -%}
{{ heading_selectors }} {
text-transform: {{ theme.heading_style }};
}
{%- endif %}

{% include "frappe/templates/includes/website_theme/navbar.css" %}

{% include "frappe/templates/includes/website_theme/footer.css" %}

{% if theme.css -%} {% include theme.css %} {%- endif %}

{%- endif -%}

+ 50
- 0
frappe/templates/pages/website_theme.py 파일 보기

@@ -0,0 +1,50 @@
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
# MIT License. See license.txt

from __future__ import unicode_literals
import re
import frappe
from frappe.utils import cint, cstr
from frappe.website.utils import get_active_theme

no_sitemap = 1
base_template_path = "templates/pages/website_theme.css"

default_properties = {
"background_color": "#ffffff",
"top_bar_color": "#ffffff",
"top_bar_text_color": "#000000",
"footer_color": "#ffffff",
"footer_text_color": "#000000",
"font_size": "14px",
"text_color": "#000000",
"link_color": "#000000"
}

def get_context(context):
"""returns web style"""
website_theme = get_active_theme()
if not website_theme:
return {}

prepare(website_theme)

return { "theme": website_theme }

def prepare(theme):
for d in default_properties:
if not theme.get(d):
theme.set(d, default_properties[d])

webfonts = list(set(theme.get(key)
for key in ("heading_webfont", 'text_webfont') if theme.get(key)))

theme.webfont_import = "\n".join('@import url(@import url(http://fonts.googleapis.com/css?family={0}:400,300,400italic,700&subset=latin,latin-ext);)'\
.format(font.replace(" ", "+")) for font in webfonts)

# move @import from css field to the top of the css file
if theme.css and "@import url" in theme.css:
webfont_import = list(set(re.findall("@import url\([^\(\)]*\);", theme.css)))
theme.webfont_import += "\n" + "\n".join(webfont_import)
for wfimport in webfont_import:
theme.css = theme.css.replace(wfimport, "")

+ 18
- 6
frappe/utils/jinja.py 파일 보기

@@ -34,6 +34,7 @@ def get_allowed_functions_for_jenv():
import frappe.utils.data
from frappe.utils.autodoc import automodule, get_doclink, get_version
from frappe.model.document import get_controller
from frappe.website.utils import get_shade

datautils = {}
for key, obj in frappe.utils.data.__dict__.items():
@@ -81,33 +82,44 @@ def get_allowed_functions_for_jenv():
},
"get_visible_columns": \
frappe.get_attr("frappe.templates.pages.print.get_visible_columns"),
"_": frappe._
"_": frappe._,
"get_shade": get_shade
}

def get_jloader():
import frappe
if not frappe.local.jloader:
from jinja2 import ChoiceLoader, PackageLoader
from jinja2 import ChoiceLoader, PackageLoader, PrefixLoader

apps = frappe.get_installed_apps()

# put frappe at the end
apps.remove("frappe")
apps.append("frappe")

frappe.local.jloader = ChoiceLoader(
# search for something like app/templates/...
[PrefixLoader(dict(
(app, PackageLoader(app, ".")) for app in apps
))]

frappe.local.jloader = ChoiceLoader([PackageLoader(app, ".") \
for app in apps + ["frappe"]])
# search for something like templates/...
+ [PackageLoader(app, ".") for app in apps]
)

return frappe.local.jloader

def set_filters(jenv):
import frappe
from frappe.utils import global_date_format, cint, cstr, flt
from frappe.website.utils import get_hex_shade
from frappe.website.utils import get_shade
from markdown2 import markdown
from json import dumps

jenv.filters["global_date_format"] = global_date_format
jenv.filters["markdown"] = markdown
jenv.filters["json"] = dumps
jenv.filters["get_hex_shade"] = get_hex_shade
jenv.filters["get_shade"] = get_shade
jenv.filters["len"] = len
jenv.filters["int"] = cint
jenv.filters["str"] = cstr


+ 22
- 8
frappe/website/context.py 파일 보기

@@ -7,7 +7,7 @@ import frappe
from frappe.website.doctype.website_settings.website_settings import get_website_settings
from frappe.website.template import render_blocks
from frappe.website.router import get_route_info
from frappe.website.utils import can_cache
from frappe.website.utils import can_cache, get_active_theme

def get_context(path):
context = None
@@ -25,10 +25,6 @@ def get_context(path):

if not context:
context = get_route_info(path)

# permission may be required for rendering
context["access"] = frappe._dict({"public_read":1, "public_write":1})

context = build_context(context)
add_data_path(context)

@@ -36,16 +32,15 @@ def get_context(path):
frappe.cache().set_value(cache_key, context)

else:
context["access"] = frappe._dict({"public_read":1, "public_write":1})
add_data_path(context)

context.update(context.data or {})

return context

def build_context(sitemap_options):
def build_context(context):
"""get_context method of doc or module is supposed to render content templates and push it into context"""
context = frappe._dict(sitemap_options)
context = frappe._dict(context)
context.update(get_website_settings())

# provide doc
@@ -64,15 +59,29 @@ def build_context(sitemap_options):
module = frappe.get_module(context.controller)

if module:
# get config fields
for prop in ("base_template_path", "template", "no_cache", "no_sitemap",
"condition_field"):
if hasattr(module, prop):
context[prop] = getattr(module, prop)

if hasattr(module, "get_context"):
ret = module.get_context(context)
if ret:
context.update(ret)

if hasattr(module, "get_children"):
context.children = module.get_children(context)

add_metatags(context)

add_website_theme(context)

# determine templates to be used
if not context.base_template_path:
app_base = frappe.get_hooks("base_template")
context.base_template_path = app_base[0] if app_base else "templates/base.html"

if context.get("base_template_path") != context.get("template") and not context.get("rendered"):
context.data = render_blocks(context)

@@ -92,4 +101,9 @@ def add_metatags(context):
if tags.get("image"):
tags["og:image"] = tags["twitter:image:src"] = tags["image"]

def add_website_theme(context):
context.bootstrap = frappe.get_hooks("bootstrap")[0]
website_theme = get_active_theme()
if website_theme and website_theme.bootstrap:
context.bootstrap = website_theme.bootstrap


+ 2
- 2
frappe/website/doctype/top_bar_item/top_bar_item.json 파일 보기

@@ -36,7 +36,7 @@
"description": "Select target = \"_blank\" to open in a new page.",
"fieldname": "target",
"fieldtype": "Select",
"in_list_view": 1,
"in_list_view": 0,
"label": "Target",
"options": "\ntarget = \"_blank\"",
"permlevel": 0
@@ -51,7 +51,7 @@
],
"idx": 1,
"istable": 1,
"modified": "2014-08-25 02:30:31.523955",
"modified": "2015-02-19 13:07:34.558311",
"modified_by": "Administrator",
"module": "Website",
"name": "Top Bar Item",


+ 104
- 77
frappe/website/doctype/web_page/web_page.json 파일 보기

@@ -20,30 +20,36 @@
"reqd": 1
},
{
"description": "Page url name (auto-generated)",
"fieldname": "page_name",
"fieldtype": "Data",
"in_list_view": 0,
"label": "Page Name",
"no_copy": 1,
"default": "1",
"fieldname": "show_title",
"fieldtype": "Check",
"label": "Show Title",
"permlevel": 0,
"read_only": 0
"precision": ""
},
{
"fieldname": "parent_web_page",
"description": "Begin this page with a slideshow of images",
"fieldname": "slideshow",
"fieldtype": "Link",
"label": "Parent Web Page",
"options": "Web Page",
"label": "Slideshow",
"options": "Website Slideshow",
"permlevel": 0
},
{
"fieldname": "parent_website_route",
"fieldtype": "Read Only",
"hidden": 1,
"label": "Parent Website Route",
"fieldname": "cb1",
"fieldtype": "Column Break",
"permlevel": 0,
"width": "50%"
},
{
"description": "Page url name (auto-generated)",
"fieldname": "page_name",
"fieldtype": "Data",
"in_list_view": 0,
"label": "Page Name",
"no_copy": 1,
"options": "",
"permlevel": 0
"permlevel": 0,
"read_only": 0
},
{
"fieldname": "published",
@@ -52,69 +58,72 @@
"permlevel": 0
},
{
"description": "0 is highest",
"fieldname": "idx",
"fieldtype": "Int",
"label": "Priority",
"description": "Page content",
"fieldname": "sb1",
"fieldtype": "Section Break",
"label": "Content",
"permlevel": 0
},
{
"fieldname": "template_path",
"fieldtype": "Data",
"label": "Template Path",
"permlevel": 0,
"read_only": 1
"description": "Content in markdown format that appears on the main side of your page",
"fieldname": "main_section",
"fieldtype": "Text Editor",
"label": "Main Section",
"permlevel": 0
},
{
"fieldname": "cb1",
"fieldtype": "Column Break",
"fieldname": "fold_10",
"fieldtype": "Fold",
"permlevel": 0,
"width": "50%"
"precision": ""
},
{
"description": "Description for page header.",
"fieldname": "description",
"fieldtype": "Small Text",
"label": "Description",
"fieldname": "custom_javascript",
"fieldtype": "Section Break",
"label": "Custom Javascript",
"permlevel": 0
},
{
"description": "Page content",
"fieldname": "sb1",
"fieldtype": "Section Break",
"label": "Content",
"description": "Add code as &lt;script&gt;",
"fieldname": "insert_code",
"fieldtype": "Check",
"label": "Insert Code",
"permlevel": 0
},
{
"description": "Begin this page with a slideshow of images",
"fieldname": "slideshow",
"fieldtype": "Link",
"label": "Slideshow",
"options": "Website Slideshow",
"depends_on": "insert_code",
"fieldname": "javascript",
"fieldtype": "Code",
"label": "Javascript",
"options": "Javascript",
"permlevel": 0
},
{
"description": "Content in markdown format that appears on the main side of your page",
"fieldname": "main_section",
"fieldtype": "Text Editor",
"label": "Main Section",
"fieldname": "custom_css",
"fieldtype": "Section Break",
"label": "Custom CSS",
"permlevel": 0
},
{
"depends_on": "eval:!doc.__islocal",
"description": "Link to other pages in the side bar and next section",
"fieldname": "sb2",
"fieldtype": "Section Break",
"label": "More",
"fieldname": "insert_style",
"fieldtype": "Check",
"label": "Insert Style",
"permlevel": 0
},
{
"description": "HTML for header section. Optional",
"fieldname": "header",
"fieldtype": "Text",
"label": "Header",
"depends_on": "insert_style",
"fieldname": "css",
"fieldtype": "Code",
"label": "CSS",
"options": "CSS",
"permlevel": 0
},
{
"fieldname": "section_break_17",
"fieldtype": "Section Break",
"permlevel": 0,
"precision": ""
},
{
"fieldname": "enable_comments",
"fieldtype": "Check",
@@ -129,51 +138,69 @@
"permlevel": 0
},
{
"fieldname": "custom_javascript",
"fieldtype": "Section Break",
"label": "Custom Javascript",
"fieldname": "column_break_20",
"fieldtype": "Column Break",
"permlevel": 0,
"precision": ""
},
{
"fieldname": "parent_web_page",
"fieldtype": "Link",
"label": "Parent Web Page",
"options": "Web Page",
"permlevel": 0
},
{
"description": "Add code as &lt;script&gt;",
"fieldname": "insert_code",
"fieldtype": "Check",
"label": "Insert Code",
"fieldname": "parent_website_route",
"fieldtype": "Read Only",
"hidden": 1,
"label": "Parent Website Route",
"no_copy": 1,
"options": "",
"permlevel": 0
},
{
"depends_on": "insert_code",
"fieldname": "javascript",
"fieldtype": "Code",
"label": "Javascript",
"options": "Javascript",
"description": "0 is highest",
"fieldname": "idx",
"fieldtype": "Int",
"label": "Priority",
"permlevel": 0
},
{
"fieldname": "custom_css",
"fieldname": "template_path",
"fieldtype": "Data",
"hidden": 0,
"label": "Template Path",
"permlevel": 0,
"read_only": 1
},
{
"depends_on": "eval:!doc.__islocal",
"description": "",
"fieldname": "sb2",
"fieldtype": "Section Break",
"label": "Custom CSS",
"label": "",
"permlevel": 0
},
{
"fieldname": "insert_style",
"fieldtype": "Check",
"label": "Insert Style",
"description": "Description for search engine optimization.",
"fieldname": "description",
"fieldtype": "Small Text",
"label": "Description",
"permlevel": 0
},
{
"depends_on": "insert_style",
"fieldname": "css",
"fieldtype": "Code",
"label": "CSS",
"options": "CSS",
"description": "HTML for header section. Optional",
"fieldname": "header",
"fieldtype": "Text",
"label": "Header",
"permlevel": 0
}
],
"icon": "icon-file-alt",
"idx": 1,
"max_attachments": 20,
"modified": "2015-02-05 05:11:48.998913",
"modified": "2015-02-20 08:30:53.345780",
"modified_by": "Administrator",
"module": "Website",
"name": "Web Page",


+ 10
- 4
frappe/website/doctype/web_page/web_page.py 파일 보기

@@ -48,13 +48,19 @@ class WebPage(WebsiteGenerator):
else:
context.update({
"style": self.css or "",
"script": self.javascript or ""
"script": self.javascript or "",
"header": self.header,
"title": self.title,
"text_align": self.text_align,
})

self.set_metatags(context)
if self.description:
context.setdefault("metatags", {})["description"] = self.description

if not self.show_title:
context["no_header"] = 1

# if not context.header:
# context.header = self.title
self.set_metatags(context)

return context



+ 229
- 192
frappe/website/doctype/website_settings/website_settings.json 파일 보기

@@ -1,261 +1,298 @@
{
"creation": "2013-04-30 12:58:46",
"docstatus": 0,
"doctype": "DocType",
"document_type": "Other",
"creation": "2013-04-30 12:58:46",
"docstatus": 0,
"doctype": "DocType",
"document_type": "Other",
"fields": [
{
"fieldname": "sb0",
"fieldtype": "Section Break",
"label": "Landing Page",
"fieldname": "sb0",
"fieldtype": "Section Break",
"label": "Landing Page",
"permlevel": 0
},
{
"description": "Link that is the website home page. Standard Links (index, login, products, blog, about, contact)",
"fieldname": "home_page",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Home Page",
"options": "",
"permlevel": 0,
},
{
"description": "Link that is the website home page. Standard Links (index, login, products, blog, about, contact)",
"fieldname": "home_page",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Home Page",
"options": "",
"permlevel": 0,
"reqd": 0
},
},
{
"description": "",
"fieldname": "title_prefix",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Title Prefix",
"description": "If checked, the Home page will be the default Item Group for the website.",
"fieldname": "home_page_is_products",
"fieldtype": "Check",
"in_list_view": 1,
"label": "Home Page is Products",
"permlevel": 0
},
},
{
"fieldname": "cb4",
"fieldtype": "Column Break",
"fieldname": "cb4",
"fieldtype": "Column Break",
"permlevel": 0
},
},
{
"description": "If checked, the Home page will be the default Item Group for the website.",
"fieldname": "home_page_is_products",
"fieldtype": "Check",
"in_list_view": 1,
"label": "Home Page is Products",
"description": "Show title in browser window as \"Prefix - title\"",
"fieldname": "title_prefix",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Title Prefix",
"permlevel": 0
},
{
"description": "Add a banner to the site. (small banners are usually good)",
"fieldname": "banner",
"fieldtype": "Section Break",
"label": "Banner",
},
{
"fieldname": "section_break_6",
"fieldtype": "Section Break",
"permlevel": 0,
"precision": ""
},
{
"default": "Standard",
"fieldname": "website_theme",
"fieldtype": "Link",
"label": "Website Theme",
"options": "Website Theme",
"permlevel": 0,
"precision": ""
},
{
"fieldname": "website_theme_image",
"fieldtype": "Image",
"label": "Website Theme Image",
"options": "website_theme_image_link",
"permlevel": 0,
"precision": ""
},
{
"fieldname": "website_theme_image_link",
"fieldtype": "Small Text",
"hidden": 1,
"label": "Website Theme Image Link",
"permlevel": 0,
"precision": ""
},
{
"description": "Add a banner to the site. (small banners are usually good)",
"fieldname": "banner",
"fieldtype": "Section Break",
"label": "Banner",
"permlevel": 0
},
},
{
"description": "Select an image of approx width 150px with a transparent background for best results.",
"fieldname": "banner_image",
"fieldtype": "Attach",
"label": "Banner Image",
"options": "",
"description": "Select an image of approx width 150px with a transparent background for best results.",
"fieldname": "banner_image",
"fieldtype": "Attach Image",
"label": "Banner Image",
"options": "",
"permlevel": 0
},
},
{
"fieldname": "set_banner_from_image",
"fieldtype": "Button",
"label": "Set Banner from Image",
"fieldname": "set_banner_from_image",
"fieldtype": "Button",
"label": "Set Banner from Image",
"permlevel": 0
},
{
"description": "Banner is above the Top Menu Bar.",
"fieldname": "banner_html",
"fieldtype": "Small Text",
"label": "Banner HTML",
},
{
"fieldname": "column_break_14",
"fieldtype": "Column Break",
"permlevel": 0,
"precision": ""
},
{
"description": "Banner is above the Top Menu Bar.",
"fieldname": "banner_html",
"fieldtype": "Small Text",
"label": "Banner HTML",
"permlevel": 0
},
},
{
"description": "Menu items in the Top Bar. For setting the color of the Top Bar, go to <a href=\"#Form/Style Settings\">Style Settings</a>",
"fieldname": "top_bar",
"fieldtype": "Section Break",
"label": "Top Bar",
"description": "Menu items in the Top Bar. For setting the color of the Top Bar, go to selected Website Theme.",
"fieldname": "top_bar",
"fieldtype": "Section Break",
"label": "Top Bar",
"permlevel": 0
},
},
{
"description": "Brand is what appears on the top-left of the toolbar. If it is an image, make sure it\nhas a transparent background and use the &lt;img /&gt; tag. Keep size as 200px x 30px",
"fieldname": "brand_html",
"fieldtype": "Small Text",
"label": "Brand HTML",
"description": "Brand is what appears on the top-left of the toolbar. If it is an image, make sure it\nhas a transparent background and use the &lt;img /&gt; tag. Keep size as 200px x 30px",
"fieldname": "brand_html",
"fieldtype": "Small Text",
"label": "Brand HTML",
"permlevel": 0
},
},
{
"fieldname": "top_bar_items",
"fieldtype": "Table",
"label": "Top Bar Items",
"options": "Top Bar Item",
"fieldname": "top_bar_items",
"fieldtype": "Table",
"label": "Top Bar Items",
"options": "Top Bar Item",
"permlevel": 0
},
},
{
"description": "Sidebar Links for Home Page only",
"fieldname": "sidebar",
"fieldtype": "Section Break",
"label": "Sidebar",
"description": "Sidebar Links for Home Page only",
"fieldname": "sidebar",
"fieldtype": "Section Break",
"label": "Sidebar",
"permlevel": 0
},
},
{
"description": "Hide the sidebar",
"fieldname": "no_sidebar",
"fieldtype": "Check",
"label": "No Sidebar",
"description": "Hide the sidebar",
"fieldname": "no_sidebar",
"fieldtype": "Check",
"label": "No Sidebar",
"permlevel": 0
},
},
{
"fieldname": "sidebar_items",
"fieldtype": "Table",
"label": "Sidebar Items",
"options": "Top Bar Item",
"fieldname": "sidebar_items",
"fieldtype": "Table",
"label": "Sidebar Items",
"options": "Top Bar Item",
"permlevel": 0
},
},
{
"fieldname": "footer",
"fieldtype": "Section Break",
"label": "Footer",
"fieldname": "footer",
"fieldtype": "Section Break",
"label": "Footer",
"permlevel": 0
},
},
{
"description": "Address and other legal information you may want to put in the footer.",
"fieldname": "address",
"fieldtype": "Text Editor",
"label": "Address",
"fieldname": "copyright",
"fieldtype": "Data",
"label": "Copyright",
"permlevel": 0
},
},
{
"fieldname": "copyright",
"fieldtype": "Data",
"label": "Copyright",
"description": "Address and other legal information you may want to put in the footer.",
"fieldname": "address",
"fieldtype": "Text Editor",
"label": "Address",
"permlevel": 0
},
},
{
"fieldname": "footer_items",
"fieldtype": "Table",
"label": "Footer Items",
"options": "Top Bar Item",
"fieldname": "footer_items",
"fieldtype": "Table",
"label": "Footer Items",
"options": "Top Bar Item",
"permlevel": 0
},
},
{
"fieldname": "integrations",
"fieldtype": "Section Break",
"label": "Integrations",
"fieldname": "integrations",
"fieldtype": "Section Break",
"label": "Integrations",
"permlevel": 0
},
},
{
"description": "Add Google Analytics ID: eg. UA-89XXX57-1. Please search help on Google Analytics for more information.",
"fieldname": "google_analytics_id",
"fieldtype": "Data",
"label": "Google Analytics ID",
"description": "Add Google Analytics ID: eg. UA-89XXX57-1. Please search help on Google Analytics for more information.",
"fieldname": "google_analytics_id",
"fieldtype": "Data",
"label": "Google Analytics ID",
"permlevel": 0
},
},
{
"fieldname": "column_break_17",
"fieldtype": "Column Break",
"fieldname": "column_break_17",
"fieldtype": "Column Break",
"permlevel": 0
},
},
{
"fieldname": "google_plus_one",
"fieldtype": "Check",
"label": "Google Plus One",
"fieldname": "google_plus_one",
"fieldtype": "Check",
"label": "Google Plus One",
"permlevel": 0
},
},
{
"fieldname": "facebook_share",
"fieldtype": "Check",
"label": "Facebook Share",
"fieldname": "facebook_share",
"fieldtype": "Check",
"label": "Facebook Share",
"permlevel": 0
},
},
{
"fieldname": "linked_in_share",
"fieldtype": "Check",
"label": "Linked In Share",
"fieldname": "linked_in_share",
"fieldtype": "Check",
"label": "Linked In Share",
"permlevel": 0
},
},
{
"fieldname": "twitter_share",
"fieldtype": "Check",
"label": "Twitter Share",
"fieldname": "twitter_share",
"fieldtype": "Check",
"label": "Twitter Share",
"permlevel": 0
},
},
{
"description": "Tweet will be shared via your user account (if specified)",
"fieldname": "twitter_share_via",
"fieldtype": "Data",
"label": "Twitter Share via",
"description": "Tweet will be shared via your user account (if specified)",
"fieldname": "twitter_share_via",
"fieldtype": "Data",
"label": "Twitter Share via",
"permlevel": 0
},
},
{
"fieldname": "misc_section",
"fieldtype": "Section Break",
"label": "Misc",
"fieldname": "misc_section",
"fieldtype": "Section Break",
"label": "Misc",
"permlevel": 0
},
},
{
"description": "An icon file with .ico extension. Should be 16 x 16 px. Generated using a favicon generator. [<a href=\"http://favicon-generator.org/\" target=\"_blank\">favicon-generator.org</a>]",
"fieldname": "favicon",
"fieldtype": "Attach",
"label": "FavIcon",
"options": "",
"description": "An icon file with .ico extension. Should be 16 x 16 px. Generated using a favicon generator. [<a href=\"http://favicon-generator.org/\" target=\"_blank\">favicon-generator.org</a>]",
"fieldname": "favicon",
"fieldtype": "Attach",
"label": "FavIcon",
"options": "",
"permlevel": 0
},
{
"description": "Sub-domain provided by erpnext.com",
"fieldname": "subdomain",
"fieldtype": "Text",
"label": "Subdomain",
"permlevel": 0,
"read_only": 1,
},
{
"description": "Sub-domain provided by erpnext.com",
"fieldname": "subdomain",
"fieldtype": "Text",
"label": "Subdomain",
"permlevel": 0,
"read_only": 1,
"reqd": 0
},
},
{
"fieldname": "column_break_28",
"fieldtype": "Column Break",
"fieldname": "column_break_28",
"fieldtype": "Column Break",
"permlevel": 0
},
},
{
"description": "Disable Customer Signup link in Login page",
"fieldname": "disable_signup",
"fieldtype": "Check",
"label": "Disable Signup",
"description": "Disable Customer Signup link in Login page",
"fieldname": "disable_signup",
"fieldtype": "Check",
"label": "Disable Signup",
"permlevel": 0
}
],
"icon": "icon-cog",
"idx": 1,
"issingle": 1,
"max_attachments": 10,
"modified": "2015-02-19 09:29:09.956095",
"modified_by": "Administrator",
"module": "Website",
"name": "Website Settings",
"owner": "Administrator",
],
"icon": "icon-cog",
"idx": 1,
"issingle": 1,
"max_attachments": 10,
"modified": "2015-02-19 22:00:27.068967",
"modified_by": "Administrator",
"module": "Website",
"name": "Website Settings",
"owner": "Administrator",
"permissions": [
{
"cancel": 0,
"create": 1,
"delete": 0,
"email": 1,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 0,
"role": "Website Manager",
"share": 1,
"submit": 0,
"cancel": 0,
"create": 1,
"delete": 0,
"email": 1,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 0,
"role": "Website Manager",
"share": 1,
"submit": 0,
"write": 1
},
{
"amend": 0,
"cancel": 0,
"create": 0,
"delete": 0,
"permlevel": 1,
"read": 1,
"report": 0,
"role": "All",
},
{
"amend": 0,
"cancel": 0,
"create": 0,
"delete": 0,
"permlevel": 1,
"read": 1,
"report": 0,
"role": "All",
"submit": 0
}
]
}
}

+ 3
- 0
frappe/website/doctype/website_settings/website_settings.py 파일 보기

@@ -42,6 +42,9 @@ class WebsiteSettings(Document):
footer_item.parent_label = None

def on_update(self):
self.clear_cache()

def clear_cache(self):
# make js and css
# clear web cache (for menus!)



+ 0
- 0
frappe/website/doctype/website_theme/__init__.py 파일 보기


+ 6
- 0
frappe/website/doctype/website_theme/test_records.json 파일 보기

@@ -0,0 +1,6 @@
[
{
"doctype": "Website Theme",
"name": "_Test Website Theme 1"
}
]

+ 10
- 0
frappe/website/doctype/website_theme/test_website_theme.py 파일 보기

@@ -0,0 +1,10 @@
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
# See license.txt

import frappe
import unittest

test_records = frappe.get_test_records('Website Theme')

class TestWebsiteTheme(unittest.TestCase):
pass

+ 27
- 0
frappe/website/doctype/website_theme/website_theme.js 파일 보기

@@ -0,0 +1,27 @@
// Copyright (c) 2015, Web Notes Technologies Pvt. Ltd. and Contributors
// MIT License. See license.txt

frappe.require('assets/frappe/js/lib/jscolor/jscolor.js');

frappe.provide("frappe.website_theme");
$.extend(frappe.website_theme, {
color_variables: ["background_color", "top_bar_color", "top_bar_text_color",
"footer_color", "footer_text_color", "text_color", "link_color",
"page_header_color", "page_header_text_color"]
});

frappe.ui.form.on("Website Theme", "onload_post_render", function(frm) {
$.each(frappe.website_theme.color_variables, function(i, v) {
$(frm.fields_dict[v].input).addClass('color {required:false,hash:true}');
});
jscolor.bind();
});

frappe.ui.form.on("Website Theme", "refresh", function(frm) {
frm.toggle_display(["module", "custom"], !!frappe.boot.developer_mode);
if (!frm.doc.custom && !!!frappe.boot.developer_mode) {
frm.set_read_only();
frm.disable_save();
}

});

+ 333
- 0
frappe/website/doctype/website_theme/website_theme.json 파일 보기

@@ -0,0 +1,333 @@
{
"allow_copy": 0,
"allow_import": 1,
"allow_rename": 0,
"autoname": "field:theme",
"creation": "2015-02-18 12:46:38.168929",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "Master",
"fields": [
{
"allow_on_submit": 0,
"fieldname": "theme",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Theme",
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 1,
"set_only_once": 0
},
{
"allow_on_submit": 0,
"default": "Website",
"fieldname": "module",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Module",
"no_copy": 0,
"options": "Module Def",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0
},
{
"default": "1",
"description": "This must be checked if the below style settings are applicable",
"fieldname": "apply_style",
"fieldtype": "Check",
"hidden": 0,
"label": "Apply Style",
"permlevel": 0,
"precision": ""
},
{
"default": "1",
"fieldname": "custom",
"fieldtype": "Check",
"label": "Custom?",
"permlevel": 0,
"precision": ""
},
{
"allow_on_submit": 0,
"fieldname": "column_break_2",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0
},
{
"description": "Link to your Bootstrap theme",
"fieldname": "bootstrap",
"fieldtype": "Small Text",
"label": "Link to Bootstrap CSS",
"permlevel": 0,
"precision": ""
},
{
"fieldname": "section_break_14",
"fieldtype": "Section Break",
"permlevel": 0,
"precision": ""
},
{
"default": "",
"fieldname": "font_size",
"fieldtype": "Select",
"label": "Font Size",
"options": "\n12px\n13px\n14px\n15px\n16px\n17px\n18px",
"permlevel": 0,
"precision": ""
},
{
"description": "Add the name of a <a href=\"https://www.google.com/fonts/\" target=\"_blank\">Google Web Font</a> e.g. \"Open Sans\"",
"fieldname": "text_webfont",
"fieldtype": "Data",
"label": "Google Font (Text)",
"permlevel": 0,
"precision": ""
},
{
"description": "Add the name of a <a href=\"https://www.google.com/fonts/\" target=\"_blank\">Google Web Font</a> e.g. \"Open Sans\"",
"fieldname": "heading_webfont",
"fieldtype": "Data",
"label": "Google Font (Heading)",
"permlevel": 0,
"precision": ""
},
{
"fieldname": "column_break_18",
"fieldtype": "Column Break",
"permlevel": 0,
"precision": ""
},
{
"fieldname": "text_color",
"fieldtype": "Data",
"label": "Text Color",
"permlevel": 0,
"precision": ""
},
{
"fieldname": "link_color",
"fieldtype": "Data",
"label": "Link Color",
"permlevel": 0,
"precision": ""
},
{
"fieldname": "heading_style",
"fieldtype": "Select",
"label": "Heading Style",
"options": "\nUPPERCASE\nTitle Case\nlowercase",
"permlevel": 0,
"precision": ""
},
{
"fieldname": "section_break_8",
"fieldtype": "Section Break",
"permlevel": 0,
"precision": ""
},
{
"fieldname": "top_bar_color",
"fieldtype": "Data",
"label": "Top Bar Color",
"permlevel": 0,
"precision": ""
},
{
"fieldname": "top_bar_text_color",
"fieldtype": "Data",
"label": "Top Bar Text Color",
"permlevel": 0,
"precision": ""
},
{
"fieldname": "page_header_color",
"fieldtype": "Data",
"label": "Page Header Color",
"permlevel": 0,
"precision": ""
},
{
"fieldname": "page_header_text_color",
"fieldtype": "Data",
"label": "Page Header Text Color",
"permlevel": 0,
"precision": ""
},
{
"fieldname": "column_break_11",
"fieldtype": "Column Break",
"permlevel": 0,
"precision": ""
},
{
"fieldname": "footer_color",
"fieldtype": "Data",
"label": "Footer Color",
"permlevel": 0,
"precision": ""
},
{
"fieldname": "footer_text_color",
"fieldtype": "Data",
"label": "Footer Text Color",
"permlevel": 0,
"precision": ""
},
{
"fieldname": "section_break_4",
"fieldtype": "Section Break",
"permlevel": 0,
"precision": ""
},
{
"fieldname": "background_color",
"fieldtype": "Data",
"label": "Background Color",
"permlevel": 0,
"precision": ""
},
{
"fieldname": "column_break_6",
"fieldtype": "Column Break",
"permlevel": 0,
"precision": ""
},
{
"description": "If image is selected, color will be ignored.",
"fieldname": "background_image",
"fieldtype": "Attach Image",
"label": "Background Image",
"permlevel": 0,
"precision": ""
},
{
"fieldname": "section_break_21",
"fieldtype": "Section Break",
"permlevel": 0,
"precision": ""
},
{
"description": "",
"fieldname": "css",
"fieldtype": "Code",
"label": "Style using CSS",
"permlevel": 0,
"precision": ""
},
{
"fieldname": "section_break_25",
"fieldtype": "Section Break",
"permlevel": 0,
"precision": ""
},
{
"fieldname": "website_theme_templates",
"fieldtype": "Table",
"label": "Website Theme Templates",
"options": "Website Theme Template",
"permlevel": 0,
"precision": "",
"reqd": 0
}
],
"hide_heading": 0,
"hide_toolbar": 0,
"in_create": 0,
"in_dialog": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 0,
"modified": "2015-02-19 20:44:42.586242",
"modified_by": "Administrator",
"module": "Website",
"name": "Website Theme",
"name_case": "",
"owner": "Administrator",
"permissions": [
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 0,
"delete": 0,
"email": 0,
"export": 0,
"import": 0,
"permlevel": 0,
"print": 0,
"read": 1,
"report": 0,
"role": "All",
"set_user_permissions": 0,
"share": 0,
"submit": 0,
"write": 0
},
{
"create": 1,
"delete": 1,
"permlevel": 0,
"read": 1,
"role": "Website Manager",
"write": 1
},
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 1,
"delete": 1,
"email": 0,
"export": 1,
"import": 1,
"permlevel": 0,
"print": 0,
"read": 1,
"report": 0,
"role": "Administrator",
"set_user_permissions": 0,
"share": 0,
"submit": 0,
"write": 1
}
],
"read_only": 0,
"read_only_onload": 0,
"search_fields": "",
"sort_field": "modified",
"sort_order": "DESC",
"title_field": ""
}

+ 54
- 0
frappe/website/doctype/website_theme/website_theme.py 파일 보기

@@ -0,0 +1,54 @@
# Copyright (c) 2015, Web Notes Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt

from __future__ import unicode_literals
import frappe
from frappe import _
from frappe.model.document import Document

class WebsiteTheme(Document):
def validate(self):
self.validate_if_customizable()

def on_update(self):
if (not self.custom
and frappe.local.conf.get('developer_mode')
and not (frappe.flags.in_import or frappe.flags.in_test)):

self.export_doc()

self.clear_cache_if_current_theme()

def is_standard_and_not_valid_user(self):
return (not self.custom
and not frappe.local.conf.get('developer_mode')
and not (frappe.flags.in_import or frappe.flags.in_test))

def on_trash(self):
if self.is_standard_and_not_valid_user():
frappe.throw(_("You are not allowed to delete a standard Website Theme"),
frappe.PermissionError)

def validate_if_customizable(self):
if self.is_standard_and_not_valid_user():
frappe.throw(_("Please Duplicate this Website Theme to customize."))

def export_doc(self):
"""Export to standard folder `[module]/website_theme/[name]/[name].json`."""
from frappe.modules.export_file import export_to_files
export_to_files(record_list=[['Website Theme', self.name]])


def clear_cache_if_current_theme(self):
website_settings = frappe.get_doc("Website Settings", "Website Settings")
if website_settings.website_theme == self.name:
website_settings.clear_cache()

def use_theme(self):
use_theme(self.name)

@frappe.whitelist()
def use_theme(theme):
website_settings = frappe.get_doc("Website Settings", "Website Settings")
website_settings.website_theme = theme
website_settings.save()

+ 0
- 0
frappe/website/doctype/website_theme_template/__init__.py 파일 보기


+ 86
- 0
frappe/website/doctype/website_theme_template/website_theme_template.json 파일 보기

@@ -0,0 +1,86 @@
{
"allow_copy": 0,
"allow_import": 0,
"allow_rename": 0,
"creation": "2015-02-18 14:52:45.383419",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "Other",
"fields": [
{
"allow_on_submit": 0,
"fieldname": "template_key",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Template Key",
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0
},
{
"allow_on_submit": 0,
"fieldname": "column_break_2",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0
},
{
"allow_on_submit": 0,
"fieldname": "template_path",
"fieldtype": "Small Text",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Template Path",
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0
}
],
"hide_heading": 0,
"hide_toolbar": 0,
"in_create": 0,
"in_dialog": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"modified": "2015-02-18 16:04:09.914591",
"modified_by": "Administrator",
"module": "Website",
"name": "Website Theme Template",
"name_case": "",
"owner": "Administrator",
"permissions": [],
"read_only": 0,
"read_only_onload": 0,
"sort_field": "modified",
"sort_order": "DESC"
}

+ 9
- 0
frappe/website/doctype/website_theme_template/website_theme_template.py 파일 보기

@@ -0,0 +1,9 @@
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt

from __future__ import unicode_literals
import frappe
from frappe.model.document import Document

class WebsiteThemeTemplate(Document):
pass

+ 6
- 6
frappe/website/js/website.js 파일 보기

@@ -441,11 +441,6 @@ $.extend(frappe, {
if(!$(".page-sidebar").hasClass("hidden-xs")) {
$(".toggle-sidebar").trigger("click");
}

// TODO add private pages to sidebar
// if(website.private_pages && $(".page-sidebar").length) {
// $(website.private_pages).prependTo(".page-sidebar");
// }
}
});

@@ -576,6 +571,11 @@ $(document).ready(function() {
$(".toggle-sidebar i").toggleClass("icon-rotate-180");
});

// collapse navbar on click
$('.navbar-collapse a').click(function(){
$(".navbar-collapse.collapse.in").collapse('hide');
});

// switch to app link
if(getCookie("system_user")==="yes") {
$("#website-post-login .dropdown-menu").append('<li class="divider"></li>\
@@ -583,7 +583,7 @@ $(document).ready(function() {
}

frappe.render_user();
frappe.setup_push_state()
frappe.setup_push_state();

$(document).trigger("page-change");
});


+ 0
- 14
frappe/website/router.py 파일 보기

@@ -26,24 +26,10 @@ def build_route(path):
if not context:
raise frappe.DoesNotExistError

if context.controller:
module = frappe.get_module(context.controller)

# get sitemap config fields too
for prop in ("base_template_path", "template", "no_cache", "no_sitemap",
"condition_field"):
if hasattr(module, prop):
context[prop] = getattr(module, prop)

context.doctype = context.ref_doctype
context.title = context.page_title
context.pathname = path

# determine templates to be used
if not context.base_template_path:
app_base = frappe.get_hooks("base_template")
context.base_template_path = app_base[0] if app_base else "templates/base.html"

return context

def resolve_route(path):


+ 31
- 24
frappe/website/template.py 파일 보기

@@ -30,44 +30,57 @@ def render_blocks(context):

_render_blocks(context["template"])

out["no_breadcrumbs"] = context.get("no_breadcrumbs", 0) or ("<!-- no-breadcrumbs -->" in out.get("content", ""))
out["no_sidebar"] = context.get("no_sidebar", 0) or ("<!-- no-sidebar -->" in out.get("content", ""))
out["no_header"] = context.get("no_header", 0) or ("<!-- no-header -->" in out.get("content", ""))

# default blocks if not found
if "title" not in out and out.get("header"):
out["title"] = out["header"]

# title
if "<!-- title:" in out.get("content", ""):
out["title"] = re.findall('<!-- title:([^>]*) -->', out.get("content"))[0].strip()

if "title" not in out:
out["title"] = context.get("title")

# header
if out["no_header"]:
out["header"] = ""
else:
if "title" not in out and out.get("header"):
out["title"] = out["header"]

if not out.get("header") and "<h1" not in out.get("content", ""):
if out.get("title"):
out["header"] = out["title"]

if not out.get("header") and "<h1" not in out.get("content", "") \
and not "<!-- no-header -->" in out.get("content"):
if out.get("title"):
out["header"] = out["title"]
if out.get("header") and not re.findall("<h.>", out["header"]):
out["header"] = "<h1>" + out["header"] + "</h1>"

if out.get("header") and not out["header"].startswith("<h"):
out["header"] = "<h1>" + out["header"] + "</h1>"
out["title"] = strip_html(out.get("title") or "")

if "breadcrumbs" not in out:
# breadcrumbs
if not out["no_breadcrumbs"] and "breadcrumbs" not in out:
out["breadcrumbs"] = scrub_relative_urls(
frappe.get_template("templates/includes/breadcrumbs.html").render(context))

# sidebar
if not out.get("no_sidebar") and "sidebar" not in out:
out["sidebar"] = scrub_relative_urls(
frappe.get_template("templates/includes/sidebar.html").render(context))

# meta
if "meta_block" not in out:
out["meta_block"] = frappe.get_template("templates/includes/meta_block.html").render(context)


out["no_sidebar"] = context.get("no_sidebar", 0)

if "<!-- no-sidebar -->" in out.get("content", ""):
out["no_sidebar"] = 1

if "<!-- title:" in out.get("content", ""):
out["title"] = re.findall('<!-- title:([^>]*) -->', out.get("content"))[0].strip()

# table of contents
if "{index}" in out.get("content", "") and context.get("children"):
html = frappe.get_template("templates/includes/static_index.html").render({
"items": context["children"]})

out["content"] = out["content"].replace("{index}", html)

# next and previous
if "{next}" in out.get("content", ""):
next_item = context.doc.get_next()
if next_item:
@@ -75,12 +88,6 @@ def render_blocks(context):
html = '<p><br><a href="{name}">'+_("Next")+': {title}</a></p>'.format(**next_item)
out["content"] = out["content"].replace("{next}", html)

if "sidebar" not in out and not out.get("no_sidebar"):
out["sidebar"] = scrub_relative_urls(
frappe.get_template("templates/includes/sidebar.html").render(context))

out["title"] = strip_html(out.get("title") or "")

# remove style and script tags from blocks
out["style"] = re.sub("</?style[^<>]*>", "", out.get("style") or "")
out["script"] = re.sub("</?script[^<>]*>", "", out.get("script") or "")


+ 74
- 16
frappe/website/utils.py 파일 보기

@@ -66,6 +66,11 @@ def is_signup_enabled():

return frappe.local.is_signup_enabled

def get_active_theme():
website_theme = frappe.db.get_value("Website Settings", "Website Settings", "website_theme")
if website_theme:
return frappe.get_doc("Website Theme", website_theme)

def cleanup_page_name(title):
"""make page name from title"""
name = title.lower()
@@ -79,21 +84,12 @@ def cleanup_page_name(title):

return name

def get_hex_shade(color, percent):
def p(c):
v = int(c, 16) + int(int('ff', 16) * (float(percent)/100))
if v < 0:
v=0
if v > 255:
v=255
h = hex(v)[2:]
if len(h) < 2:
h = "0" + h
return h

r, g, b = color[0:2], color[2:4], color[4:6]

avg = (float(int(r, 16) + int(g, 16) + int(b, 16)) / 3)

def get_shade(color, percent):
color, color_format = detect_color_format(color)
r, g, b, a = color

avg = (float(int(r) + int(g) + int(b)) / 3)
# switch dark and light shades
if avg > 128:
percent = -percent
@@ -102,4 +98,66 @@ def get_hex_shade(color, percent):
if percent < 25 and avg < 64:
percent = percent * 2

return p(r) + p(g) + p(b)
new_color = []
for channel_value in (r, g, b):
new_color.append(get_shade_for_channel(channel_value, percent))

r, g, b = new_color

return format_color(r, g, b, a, color_format)


def detect_color_format(color):
if color.startswith("rgba"):
color_format = "rgba"
color = [c.strip() for c in color[5:-1].split(",")]

elif color.startswith("rgb"):
color_format = "rgb"
color = [c.strip() for c in color[4:-1].split(",")] + [1]

else:
# assume hex
color_format = "hex"

if color.startswith("#"):
color = color[1:]

if len(color) == 3:
# hex in short form like #fff
color = "{0}{0}{1}{1}{2}{2}".format(*tuple(color))

color = [int(color[0:2], 16), int(color[2:4], 16), int(color[4:6], 16), 1]

return color, color_format


def get_shade_for_channel(channel_value, percent):
v = int(channel_value) + int(int('ff', 16) * (float(percent)/100))
if v < 0:
v=0
if v > 255:
v=255

return v


def format_color(r, g, b, a, color_format):
if color_format == "rgba":
return "rgba({0}, {1}, {2}, {3})".format(r, g, b, a)

elif color_format == "rgb":
return "rgb({0}, {1}, {2})".format(r, g, b)

else:
# assume hex
return "#{0}{1}{2}".format(convert_to_hex(r), convert_to_hex(g), convert_to_hex(b))


def convert_to_hex(channel_value):
h = hex(channel_value)[2:]

if len(h) < 2:
h = "0" + h

return h

+ 3
- 3
frappe/website/website_generator.py 파일 보기

@@ -142,7 +142,7 @@ class WebsiteGenerator(Document):
if context.parents:
return context.parents

home_page = get_home_page()
# home_page = get_home_page()

parents = []
me = self
@@ -151,8 +151,8 @@ class WebsiteGenerator(Document):
_parent_val = me.get(_parent_field) if _parent_field else None

# if no parent and not home page, then parent is home page
if not _parent_val and me.get_route() != home_page:
_parent_val = home_page
# if not _parent_val and me.get_route() != home_page:
# _parent_val = home_page

if _parent_val:
df = me.meta.get_field(_parent_field)


+ 0
- 0
frappe/website/website_theme/__init__.py 파일 보기


+ 0
- 0
frappe/website/website_theme/standard/__init__.py 파일 보기


+ 16
- 0
frappe/website/website_theme/standard/standard.json 파일 보기

@@ -0,0 +1,16 @@
{
"apply_style": 1,
"creation": "2015-02-19 13:37:33.925909",
"custom": 0,
"docstatus": 0,
"doctype": "Website Theme",
"font_size": "14px",
"heading_style": "",
"modified": "2015-02-19 20:01:19.478005",
"modified_by": "Administrator",
"module": "Website",
"name": "Standard",
"owner": "Administrator",
"theme": "Standard",
"website_theme_templates": []
}

불러오는 중...
취소
저장