diff --git a/frappe/core/doctype/doctype/doctype.py b/frappe/core/doctype/doctype/doctype.py index 40f883a5be..93bb041820 100644 --- a/frappe/core/doctype/doctype/doctype.py +++ b/frappe/core/doctype/doctype/doctype.py @@ -3,7 +3,7 @@ from __future__ import unicode_literals -import re, copy +import re, copy, os import MySQLdb import frappe from frappe import _ @@ -197,6 +197,9 @@ class DocType(Document): self.export_doc() self.make_controller_template() + if self.has_web_view: + self.set_base_class_for_controller() + # update index if not self.custom: self.run_module_method("on_doctype_update") @@ -226,6 +229,26 @@ class DocType(Document): frappe.enqueue('frappe.utils.global_search.rebuild_for_doctype', now=now, doctype=self.name) + def set_base_class_for_controller(self): + '''Updates the controller class to subclass from `WebsiteGenertor`, + if it is a subclass of `Document`''' + controller_path = frappe.get_module_path(frappe.scrub(self.module), + 'doctype', frappe.scrub(self.name), frappe.scrub(self.name) + '.py') + + with open(controller_path, 'r') as f: + code = f.read() + + class_string = '\nclass {0}(Document)'.format(self.name.replace(' ', '')) + if '\nfrom frappe.model.document import Document' in code and class_string in code: + code = code.replace('from frappe.model.document import Document', + 'from frappe.website.website_generator import WebsiteGenerator') + code = code.replace('class {0}(Document)'.format(self.name.replace(' ', '')), + 'class {0}(WebsiteGenerator)'.format(self.name.replace(' ', ''))) + + with open(controller_path, 'w') as f: + f.write(code) + + def run_module_method(self, method): from frappe.modules import load_doctype_module module = load_doctype_module(self.name, self.module) @@ -297,6 +320,9 @@ class DocType(Document): make_boilerplate("controller.js", self.as_dict()) if self.has_web_view: + templates_path = frappe.get_module_path(frappe.scrub(self.module), 'doctype', frappe.scrub(self.name), 'templates') + if not os.path.exists(templates_path): + os.makedirs(templates_path) make_boilerplate('templates/controller.html', self.as_dict()) make_boilerplate('templates/controller_row.html', self.as_dict()) diff --git a/frappe/database.py b/frappe/database.py index 7a7e674b31..da360478c0 100644 --- a/frappe/database.py +++ b/frappe/database.py @@ -17,7 +17,7 @@ import re import frappe.model.meta from frappe.utils import now, get_datetime, cstr from frappe import _ -from types import StringType, UnicodeType +from types import StringType, UnicodeType from frappe.utils.global_search import sync_global_search class Database: @@ -799,9 +799,13 @@ class Database: where creation >= %s""".format(doctype=doctype), now_datetime() - relativedelta(minutes=minutes))[0][0] + def get_db_table_columns(self, table): + """Returns list of column names from given table.""" + return [r[0] for r in self.sql("DESC `%s`" % table)] + def get_table_columns(self, doctype): """Returns list of column names from given doctype.""" - return [r[0] for r in self.sql("DESC `tab%s`" % doctype)] + return self.get_db_table_columns('tab' + doctype) def has_column(self, doctype, column): """Returns True if column exists in database.""" diff --git a/frappe/hooks.py b/frappe/hooks.py index 136b16f6db..41fa4ab667 100755 --- a/frappe/hooks.py +++ b/frappe/hooks.py @@ -46,7 +46,6 @@ web_include_css = [ "assets/css/frappe-web.css" ] website_route_rules = [ - {"from_route": "/blog", "to_route": "Blog Post"}, {"from_route": "/blog/", "to_route": "Blog Post"}, {"from_route": "/kb/", "to_route": "Help Article"} ] @@ -57,9 +56,6 @@ notification_config = "frappe.core.notifications.get_notification_config" before_tests = "frappe.utils.install.before_tests" -website_generators = ["Web Page", "Blog Post", "Blog Category", "Web Form", - "Help Article"] - email_append_to = ["Event", "ToDo", "Communication"] calendars = ["Event"] diff --git a/frappe/migrate.py b/frappe/migrate.py index 222e009c07..9922385e0d 100644 --- a/frappe/migrate.py +++ b/frappe/migrate.py @@ -10,11 +10,11 @@ import frappe.model.sync from frappe.utils.fixtures import sync_fixtures from frappe.sessions import clear_global_cache from frappe.desk.notifications import clear_notifications -from frappe.website import render +from frappe.website import render, router from frappe.desk.doctype.desktop_icon.desktop_icon import sync_desktop_icons from frappe.core.doctype.language.language import sync_languages from frappe.modules.utils import sync_customizations -import frappe.utils.help +import frappe.utils.help def migrate(verbose=True, rebuild_website=False): '''Migrate all apps to the latest version, will: @@ -41,6 +41,9 @@ def migrate(verbose=True, rebuild_website=False): # syncs statics render.clear_cache() + # add static pages to global search + router.sync_global_search() + frappe.db.commit() if not frappe.conf.get('global_help_setup'): diff --git a/frappe/model/document.py b/frappe/model/document.py index 8f3025ba51..e6b97b2385 100644 --- a/frappe/model/document.py +++ b/frappe/model/document.py @@ -336,6 +336,10 @@ class Document(BaseDocument): for d in self.get_all_children(): set_new_name(d) + def get_title(self): + '''Get the document title based on title_field or `title` or `name`''' + return self.get(self.meta.get_title_field()) + def set_title_field(self): """Set title field based on template""" def get_values(): diff --git a/frappe/model/meta.py b/frappe/model/meta.py index 6435646101..f792e1c809 100644 --- a/frappe/model/meta.py +++ b/frappe/model/meta.py @@ -203,7 +203,15 @@ class Meta(Document): return [d for d in self.fields if d.get('is_custom_field')] def get_title_field(self): - return self.title_field or "name" + '''Return the title field of this doctype, + explict via `title_field`, or `title` or `name`''' + title_field = getattr(self, 'title_field', None) + if not title_field and self.has_field('title'): + title_field = 'title' + else: + title_field = 'name' + + return title_field def process(self): # don't process for special doctypes diff --git a/frappe/patches.txt b/frappe/patches.txt index d54b0f00fa..0054e6484f 100644 --- a/frappe/patches.txt +++ b/frappe/patches.txt @@ -171,3 +171,4 @@ execute:frappe.rename_doc('Country', 'Syrian Arab Republic', 'Syria', ignore_if_ frappe.patches.v8_0.rename_listsettings_to_usersettings frappe.patches.v7_2.update_communications frappe.patches.v8_0.drop_in_dialog +frappe.patches.v8_0.update_published_in_global_search diff --git a/frappe/patches/v8_0/update_published_in_global_search.py b/frappe/patches/v8_0/update_published_in_global_search.py new file mode 100644 index 0000000000..09aa33706b --- /dev/null +++ b/frappe/patches/v8_0/update_published_in_global_search.py @@ -0,0 +1,18 @@ +import frappe +from frappe.utils.global_search import rebuild_for_doctype + +def execute(): + from frappe.website.router import get_doctypes_with_web_view + if not 'published' in frappe.db.get_db_table_columns('__global_search'): + frappe.db.sql('''alter table __global_search + add column `title` varchar(140)''') + + frappe.db.sql('''alter table __global_search + add column `route` varchar(140)''') + + frappe.db.sql('''alter table __global_search + add column `published` int(1) not null default 0''') + + for doctype in get_doctypes_with_web_view(): + rebuild_for_doctype(doctype) + diff --git a/frappe/public/css/website.css b/frappe/public/css/website.css index 6c3582c9bd..968b6fc766 100644 --- a/frappe/public/css/website.css +++ b/frappe/public/css/website.css @@ -464,6 +464,17 @@ h6 a { border-right: none; border-top: none; } +.navbar-search { + max-width: 400px; + display: inline-block; + margin: 10px; + margin-top: 9px; + padding: 2px 6px; + height: 26px; +} +.dropdown-menu .navbar-search { + max-width: 180px; +} .social-icons i { font-size: 120%; } diff --git a/frappe/public/less/website.less b/frappe/public/less/website.less index 1d7bf1ba69..5dd61f067b 100644 --- a/frappe/public/less/website.less +++ b/frappe/public/less/website.less @@ -95,6 +95,19 @@ h1, h2, h3, h4, h5, h6 { border-top: none; } +.navbar-search { + max-width: 400px; + display: inline-block; + margin: 10px; + margin-top: 9px; + padding: 2px 6px; + height: 26px; +} + +.dropdown-menu .navbar-search { + max-width: 180px; +} + .social-icons i { font-size: 120%; } diff --git a/frappe/templates/generators/__init__.py b/frappe/templates/generators/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/frappe/templates/includes/navbar/dropdown_items.html b/frappe/templates/includes/navbar/dropdown_items.html index 4d7e54c829..9acb381188 100644 --- a/frappe/templates/includes/navbar/dropdown_items.html +++ b/frappe/templates/includes/navbar/dropdown_items.html @@ -13,5 +13,6 @@ {%- endfor %} {% block navbar_right_extension %}{% endblock %}
  • +{% include "templates/includes/navbar/navbar_search.html" %} {% include "templates/includes/navbar/dropdown_login.html" %} diff --git a/frappe/templates/includes/navbar/navbar_items.html b/frappe/templates/includes/navbar/navbar_items.html index 1bce855241..bb4009c8cf 100644 --- a/frappe/templates/includes/navbar/navbar_items.html +++ b/frappe/templates/includes/navbar/navbar_items.html @@ -16,5 +16,6 @@ {% if not only_static %} {% block navbar_right_extension %}{% endblock %} {% endif %} + {% include "templates/includes/navbar/navbar_search.html" %} {% include "templates/includes/navbar/navbar_login.html" %} diff --git a/frappe/templates/includes/navbar/navbar_search.html b/frappe/templates/includes/navbar/navbar_search.html new file mode 100644 index 0000000000..67b4d6505a --- /dev/null +++ b/frappe/templates/includes/navbar/navbar_search.html @@ -0,0 +1,9 @@ +{% if navbar_search %} +
  • +
    + +
    +
  • +{% endif %} \ No newline at end of file diff --git a/frappe/templates/includes/search_result.html b/frappe/templates/includes/search_result.html new file mode 100644 index 0000000000..cc2d936a8a --- /dev/null +++ b/frappe/templates/includes/search_result.html @@ -0,0 +1,6 @@ +{% for d in results %} +
    +

    {{ d.title }}

    +

    {{ d.preview }}

    +
    +{% endfor %} \ No newline at end of file diff --git a/frappe/utils/boilerplate.py b/frappe/utils/boilerplate.py index 8ef2e8e425..e7ca4dddd3 100755 --- a/frappe/utils/boilerplate.py +++ b/frappe/utils/boilerplate.py @@ -52,11 +52,13 @@ def make_boilerplate(dest, app_name): frappe.create_folder(os.path.join(dest, hooks.app_name, hooks.app_name, "www")) frappe.create_folder(os.path.join(dest, hooks.app_name, hooks.app_name, "templates", "pages"), with_init=True) - frappe.create_folder(os.path.join(dest, hooks.app_name, hooks.app_name, "templates", - "generators"), with_init=True) frappe.create_folder(os.path.join(dest, hooks.app_name, hooks.app_name, "templates", "includes")) frappe.create_folder(os.path.join(dest, hooks.app_name, hooks.app_name, "config"), with_init=True) + frappe.create_folder(os.path.join(dest, hooks.app_name, hooks.app_name, "public", + "css")) + frappe.create_folder(os.path.join(dest, hooks.app_name, hooks.app_name, "public", + "js")) with open(os.path.join(dest, hooks.app_name, hooks.app_name, "__init__.py"), "w") as f: f.write(encode(init_template)) diff --git a/frappe/utils/global_search.py b/frappe/utils/global_search.py index 26637df799..8c0ec5cace 100644 --- a/frappe/utils/global_search.py +++ b/frappe/utils/global_search.py @@ -11,8 +11,11 @@ def setup_global_search_table(): frappe.db.sql('''create table __global_search( doctype varchar(100), name varchar(140), + title varchar(140), content text, fulltext(content), + route varchar(140), + published int(1) not null default 0, unique (doctype, name)) COLLATE=utf8mb4_unicode_ci ENGINE=MyISAM @@ -46,8 +49,13 @@ def update_global_search(doc): content.append(field.label + ": " + unicode(doc.get(field.fieldname))) if content: + published = 0 + if hasattr(doc, 'is_website_published') and doc.meta.allow_guest_to_view: + published = 1 if doc.is_website_published() else 0 + frappe.flags.update_global_search.append( - dict(doctype=doc.doctype, name=doc.name, content='|||'.join(content))) + dict(doctype=doc.doctype, name=doc.name, content='|||'.join(content or ''), + published=published, title=doc.get_title(), route=doc.get('route'))) def sync_global_search(): '''Add values from `frappe.flags.update_global_search` to __global_search. @@ -56,9 +64,9 @@ def sync_global_search(): for value in frappe.flags.update_global_search: frappe.db.sql(''' insert into __global_search - (doctype, name, content) + (doctype, name, content, published, title, route) values - (%(doctype)s, %(name)s, %(content)s) + (%(doctype)s, %(name)s, %(content)s, %(published)s, %(title)s, %(route)s) on duplicate key update content = %(content)s''', value) @@ -69,11 +77,13 @@ def rebuild_for_doctype(doctype): searchable fields :param doctype: Doctype ''' + frappe.flags.update_global_search = [] + frappe.db.sql(''' delete from __global_search where - doctype = (%s)''', doctype, as_dict=True) + doctype = %s''', doctype, as_dict=True) for d in frappe.get_all(doctype): update_global_search(frappe.get_doc(doctype, d.name)) @@ -88,7 +98,8 @@ def delete_for_document(doc): delete from __global_search where - name = (%s)''', (doc.name), as_dict=True) + doctype = %s and + name = %s''', (doc.doctype, doc.name), as_dict=True) @frappe.whitelist() def search(text, start=0, limit=20): @@ -109,6 +120,27 @@ def search(text, start=0, limit=20): limit {start}, {limit}'''.format(start=start, limit=limit), text, as_dict=True) return results +@frappe.whitelist(allow_guest=True) +def web_search(text, start=0, limit=20): + '''Search for given text in __global_search where published = 1 + :param text: phrase to be searched + :param start: start results at, default 0 + :param limit: number of results to return, default 20 + :return: Array of result objects''' + + text = "+" + text + "*" + results = frappe.db.sql(''' + select + doctype, name, content, title, route + from + __global_search + where + published = 1 and + match(content) against (%s IN BOOLEAN MODE) + limit {start}, {limit}'''.format(start=start, limit=limit), + text, as_dict=True) + return results + @frappe.whitelist() def get_search_doctypes(text): '''Search for all t diff --git a/frappe/website/context.py b/frappe/website/context.py index 3a632ce703..82b8da865a 100644 --- a/frappe/website/context.py +++ b/frappe/website/context.py @@ -29,8 +29,6 @@ def get_context(path, args=None): if hasattr(frappe.local, 'response') and frappe.local.response.get('context'): context.update(frappe.local.response.context) - # print frappe.as_json(context) - return context def update_controller_context(context, controller): @@ -77,15 +75,16 @@ def build_context(context): if context.doc: context.update(context.doc.as_dict()) context.update(context.doc.get_website_properties()) + + if not context.template: + context.template = context.doc.meta.get_web_template() + if hasattr(context.doc, "get_context"): ret = context.doc.get_context(context) if ret: context.update(ret) - if not context.template: - context.template = context.doc.meta.get_web_template() - for prop in ("no_cache", "no_sitemap"): if not prop in context: context[prop] = getattr(context.doc, prop, False) diff --git a/frappe/website/doctype/blog_category/blog_category.json b/frappe/website/doctype/blog_category/blog_category.json index 685d92c6d4..5921cef2d5 100644 --- a/frappe/website/doctype/blog_category/blog_category.json +++ b/frappe/website/doctype/blog_category/blog_category.json @@ -1,5 +1,6 @@ { "allow_copy": 0, + "allow_guest_to_view": 1, "allow_import": 1, "allow_rename": 0, "autoname": "field:category_name", @@ -22,6 +23,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 1, "in_standard_filter": 0, "label": "Category Name", @@ -49,6 +51,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 1, "in_standard_filter": 0, "label": "Title", @@ -76,6 +79,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 1, "in_standard_filter": 0, "label": "Published", @@ -104,6 +108,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Route", @@ -122,18 +127,19 @@ "unique": 1 } ], + "has_web_view": 1, "hide_heading": 0, "hide_toolbar": 0, "icon": "fa fa-tag", "idx": 1, "image_view": 0, "in_create": 0, - "in_dialog": 0, + "is_published_field": "published", "is_submittable": 0, "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2016-12-29 14:40:35.127314", + "modified": "2017-03-06 16:29:05.035486", "modified_by": "Administrator", "module": "Website", "name": "Blog Category", @@ -149,7 +155,6 @@ "export": 0, "if_owner": 0, "import": 0, - "is_custom": 0, "permlevel": 0, "print": 1, "read": 1, @@ -170,7 +175,6 @@ "export": 0, "if_owner": 0, "import": 0, - "is_custom": 0, "permlevel": 0, "print": 1, "read": 1, @@ -185,6 +189,7 @@ "quick_entry": 1, "read_only": 0, "read_only_onload": 0, + "show_name_in_global_search": 0, "sort_order": "DESC", "track_changes": 1, "track_seen": 0 diff --git a/frappe/templates/generators/blog_category.html b/frappe/website/doctype/blog_category/templates/blog_category.html similarity index 100% rename from frappe/templates/generators/blog_category.html rename to frappe/website/doctype/blog_category/templates/blog_category.html diff --git a/frappe/website/doctype/blog_category/templates/blog_category_row.html b/frappe/website/doctype/blog_category/templates/blog_category_row.html new file mode 100644 index 0000000000..2b999819cb --- /dev/null +++ b/frappe/website/doctype/blog_category/templates/blog_category_row.html @@ -0,0 +1,4 @@ +
    + {{ title }} +
    + \ No newline at end of file diff --git a/frappe/website/doctype/blog_post/blog_post.json b/frappe/website/doctype/blog_post/blog_post.json index 18c545c7a6..21be444dce 100644 --- a/frappe/website/doctype/blog_post/blog_post.json +++ b/frappe/website/doctype/blog_post/blog_post.json @@ -1,5 +1,6 @@ { "allow_copy": 0, + "allow_guest_to_view": 1, "allow_import": 1, "allow_rename": 0, "beta": 0, @@ -276,7 +277,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 1, "in_filter": 0, - "in_global_search": 0, + "in_global_search": 1, "in_list_view": 0, "in_standard_filter": 0, "label": "Content", @@ -322,18 +323,19 @@ "unique": 0 } ], + "has_web_view": 1, "hide_heading": 0, "hide_toolbar": 0, "icon": "fa fa-quote-left", "idx": 1, "image_view": 0, "in_create": 0, - "in_dialog": 0, + "is_published_field": "published", "is_submittable": 0, "issingle": 0, "istable": 0, "max_attachments": 5, - "modified": "2017-02-20 13:33:26.617917", + "modified": "2017-03-06 16:25:33.410910", "modified_by": "Administrator", "module": "Website", "name": "Blog Post", @@ -383,6 +385,7 @@ "quick_entry": 0, "read_only": 0, "read_only_onload": 0, + "route": "/blog", "show_name_in_global_search": 0, "sort_order": "ASC", "title_field": "title", diff --git a/frappe/website/doctype/blog_post/blog_post.py b/frappe/website/doctype/blog_post/blog_post.py index 480e04d908..34062039b5 100644 --- a/frappe/website/doctype/blog_post/blog_post.py +++ b/frappe/website/doctype/blog_post/blog_post.py @@ -12,10 +12,7 @@ from frappe.website.utils import find_first_image, get_comment_list class BlogPost(WebsiteGenerator): website = frappe._dict( - condition_field = "published", - template = "templates/generators/blog_post.html", - order_by = "published_on desc", - page_title_field = "title" + order_by = "published_on desc" ) def make_route(self): @@ -90,7 +87,6 @@ class BlogPost(WebsiteGenerator): def get_list_context(context=None): list_context = frappe._dict( template = "templates/includes/blog/blog.html", - row_template = "templates/includes/blog/blog_row.html", get_list = get_blog_list, hide_filters = True, children = get_children(), diff --git a/frappe/templates/generators/blog_post.html b/frappe/website/doctype/blog_post/templates/blog_post.html similarity index 100% rename from frappe/templates/generators/blog_post.html rename to frappe/website/doctype/blog_post/templates/blog_post.html diff --git a/frappe/templates/includes/blog/blog_row.html b/frappe/website/doctype/blog_post/templates/blog_post_row.html similarity index 100% rename from frappe/templates/includes/blog/blog_row.html rename to frappe/website/doctype/blog_post/templates/blog_post_row.html diff --git a/frappe/website/doctype/help_article/help_article.json b/frappe/website/doctype/help_article/help_article.json index 66722fc99e..577361c8af 100644 --- a/frappe/website/doctype/help_article/help_article.json +++ b/frappe/website/doctype/help_article/help_article.json @@ -1,5 +1,6 @@ { "allow_copy": 0, + "allow_guest_to_view": 1, "allow_import": 1, "allow_rename": 0, "beta": 0, @@ -21,6 +22,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 1, "in_list_view": 0, "in_standard_filter": 0, "label": "Title", @@ -49,6 +51,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 1, "in_standard_filter": 1, "label": "Category", @@ -78,6 +81,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Published", @@ -106,6 +110,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "length": 0, @@ -134,6 +139,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Author", @@ -162,6 +168,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Level", @@ -191,6 +198,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "length": 0, @@ -218,6 +226,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 1, "in_list_view": 0, "in_standard_filter": 0, "label": "Content", @@ -246,6 +255,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Likes", @@ -274,6 +284,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Route", @@ -303,6 +314,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Owner", @@ -322,18 +334,19 @@ "unique": 0 } ], + "has_web_view": 1, "hide_heading": 0, "hide_toolbar": 0, "icon": "icon-file-alt", "idx": 0, "image_view": 0, "in_create": 0, - "in_dialog": 0, + "is_published_field": "published", "is_submittable": 0, "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2016-12-29 14:39:50.018704", + "modified": "2017-03-06 16:27:58.333205", "modified_by": "Administrator", "module": "Website", "name": "Help Article", @@ -350,7 +363,6 @@ "export": 1, "if_owner": 0, "import": 1, - "is_custom": 0, "permlevel": 0, "print": 1, "read": 1, @@ -371,7 +383,6 @@ "export": 0, "if_owner": 0, "import": 0, - "is_custom": 0, "permlevel": 0, "print": 0, "read": 1, @@ -392,7 +403,6 @@ "export": 0, "if_owner": 0, "import": 0, - "is_custom": 0, "permlevel": 0, "print": 0, "read": 1, @@ -407,6 +417,7 @@ "quick_entry": 0, "read_only": 0, "read_only_onload": 0, + "show_name_in_global_search": 0, "sort_field": "modified", "sort_order": "DESC", "title_field": "title", diff --git a/frappe/website/doctype/help_article/help_article.py b/frappe/website/doctype/help_article/help_article.py index 76785577aa..9d302c89e0 100644 --- a/frappe/website/doctype/help_article/help_article.py +++ b/frappe/website/doctype/help_article/help_article.py @@ -9,11 +9,6 @@ from frappe.website.utils import get_comment_list from frappe import _ class HelpArticle(WebsiteGenerator): - website = frappe._dict( - condition_field = "published", - template = "templates/generators/help_article.html", - ) - def validate(self): self.set_route() @@ -58,7 +53,6 @@ def get_list_context(context=None): list_context = frappe._dict( title = category or _("Knowledge Base"), - row_template = "templates/includes/kb_row.html", get_level_class = get_level_class, show_sidebar = True, sidebar_items = get_sidebar_items(), diff --git a/frappe/templates/generators/help_article.html b/frappe/website/doctype/help_article/templates/help_article.html similarity index 100% rename from frappe/templates/generators/help_article.html rename to frappe/website/doctype/help_article/templates/help_article.html diff --git a/frappe/templates/includes/kb_row.html b/frappe/website/doctype/help_article/templates/help_article_row.html similarity index 100% rename from frappe/templates/includes/kb_row.html rename to frappe/website/doctype/help_article/templates/help_article_row.html diff --git a/frappe/website/doctype/portal_settings/portal_settings.py b/frappe/website/doctype/portal_settings/portal_settings.py index 9e8fe4c7bc..72fc175930 100644 --- a/frappe/website/doctype/portal_settings/portal_settings.py +++ b/frappe/website/doctype/portal_settings/portal_settings.py @@ -27,7 +27,7 @@ class PortalSettings(Document): def sync_menu(self): '''Sync portal menu items''' dirty = False - for item in frappe.get_hooks('portal_menu_items'): + for item in frappe.get_hooks('standard_portal_menu_items'): if item.get('role') and not frappe.db.exists("Role", item.get('role')): frappe.get_doc({"doctype": "Role", "role_name": item.get('role'), "desk_access": 0}).insert() if self.add_item(item): diff --git a/frappe/templates/generators/web_form.html b/frappe/website/doctype/web_form/templates/web_form.html similarity index 100% rename from frappe/templates/generators/web_form.html rename to frappe/website/doctype/web_form/templates/web_form.html diff --git a/frappe/website/doctype/web_form/web_form.json b/frappe/website/doctype/web_form/web_form.json index 407076025c..d29fe8918f 100644 --- a/frappe/website/doctype/web_form/web_form.json +++ b/frappe/website/doctype/web_form/web_form.json @@ -1,5 +1,6 @@ { "allow_copy": 0, + "allow_guest_to_view": 0, "allow_import": 0, "allow_rename": 0, "autoname": "", @@ -23,6 +24,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Title", @@ -50,6 +52,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Route", @@ -78,6 +81,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 1, "in_standard_filter": 1, "label": "Select DocType", @@ -106,6 +110,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Module", @@ -135,6 +140,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "length": 0, @@ -161,6 +167,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Is Standard", @@ -189,6 +196,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Published", @@ -216,6 +224,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Login Required", @@ -244,6 +253,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Allow Edit", @@ -272,6 +282,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Allow Multiple", @@ -300,6 +311,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Allow Delete", @@ -328,6 +340,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Allow Print", @@ -357,6 +370,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Print Format", @@ -387,6 +401,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Allow Comments", @@ -415,6 +430,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Allow Incomplete Forms", @@ -443,6 +459,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Fields", @@ -470,6 +487,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Introduction", @@ -497,6 +515,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Web Form Fields", @@ -525,6 +544,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Max Attachment Size (in MB)", @@ -553,6 +573,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Actions", @@ -581,6 +602,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Success Message", @@ -609,6 +631,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Success URL", @@ -636,6 +659,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Sidebar Settings", @@ -665,6 +689,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Show Sidebar", @@ -693,6 +718,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Sidebar Items", @@ -723,6 +749,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Payments", @@ -751,6 +778,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Accept Payment", @@ -780,6 +808,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Payment Gateway", @@ -811,6 +840,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Button Label", @@ -840,6 +870,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Button Help", @@ -868,6 +899,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "length": 0, @@ -896,6 +928,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Amount Based On Field", @@ -925,6 +958,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Amount Field", @@ -954,6 +988,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Amount", @@ -983,6 +1018,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Currency", @@ -1012,6 +1048,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Advanced", @@ -1041,6 +1078,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Web Page Link Text", @@ -1070,6 +1108,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Breadcrumbs", @@ -1088,18 +1127,19 @@ "unique": 0 } ], + "has_web_view": 1, "hide_heading": 0, "hide_toolbar": 0, "icon": "icon-edit", "idx": 0, "image_view": 0, "in_create": 0, - "in_dialog": 0, + "is_published_field": "published", "is_submittable": 0, "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2016-12-29 14:39:54.941009", + "modified": "2017-03-06 16:29:35.691485", "modified_by": "Administrator", "module": "Website", "name": "Web Form", @@ -1116,7 +1156,6 @@ "export": 0, "if_owner": 0, "import": 0, - "is_custom": 0, "permlevel": 0, "print": 0, "read": 1, @@ -1131,6 +1170,7 @@ "quick_entry": 0, "read_only": 0, "read_only_onload": 0, + "show_name_in_global_search": 0, "sort_field": "modified", "sort_order": "DESC", "title_field": "title", diff --git a/frappe/website/doctype/web_form/web_form.py b/frappe/website/doctype/web_form/web_form.py index 04b8a8130b..983772c756 100644 --- a/frappe/website/doctype/web_form/web_form.py +++ b/frappe/website/doctype/web_form/web_form.py @@ -16,9 +16,6 @@ from urllib import urlencode class WebForm(WebsiteGenerator): website = frappe._dict( - template = "templates/generators/web_form.html", - condition_field = "published", - page_title_field = "title", no_cache = 1 ) diff --git a/frappe/templates/generators/web_page.html b/frappe/website/doctype/web_page/templates/web_page.html similarity index 100% rename from frappe/templates/generators/web_page.html rename to frappe/website/doctype/web_page/templates/web_page.html diff --git a/frappe/website/doctype/web_page/web_page.json b/frappe/website/doctype/web_page/web_page.json index e8be848d9f..8a28b61cd2 100644 --- a/frappe/website/doctype/web_page/web_page.json +++ b/frappe/website/doctype/web_page/web_page.json @@ -1,5 +1,6 @@ { "allow_copy": 0, + "allow_guest_to_view": 1, "allow_import": 0, "allow_rename": 0, "beta": 0, @@ -51,7 +52,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, - "in_global_search": 0, + "in_global_search": 1, "in_list_view": 0, "in_standard_filter": 0, "label": "Title", @@ -254,7 +255,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, - "in_global_search": 0, + "in_global_search": 1, "in_list_view": 0, "in_standard_filter": 0, "label": "Main Section", @@ -764,18 +765,19 @@ "unique": 0 } ], + "has_web_view": 1, "hide_heading": 0, "hide_toolbar": 0, "icon": "fa fa-file-alt", "idx": 1, "image_view": 0, "in_create": 0, - "in_dialog": 0, + "is_published_field": "published", "is_submittable": 0, "issingle": 0, "istable": 0, "max_attachments": 20, - "modified": "2017-02-20 13:33:08.460608", + "modified": "2017-03-06 16:26:47.019511", "modified_by": "Administrator", "module": "Website", "name": "Web Page", diff --git a/frappe/website/doctype/web_page/web_page.py b/frappe/website/doctype/web_page/web_page.py index d1314ff9cc..de6deed617 100644 --- a/frappe/website/doctype/web_page/web_page.py +++ b/frappe/website/doctype/web_page/web_page.py @@ -13,12 +13,6 @@ from frappe.utils.jinja import render_template from jinja2.exceptions import TemplateSyntaxError class WebPage(WebsiteGenerator): - website = frappe._dict( - template = "templates/generators/web_page.html", - condition_field = "published", - page_title_field = "title", - ) - def get_feed(self): return self.title diff --git a/frappe/website/doctype/website_settings/website_settings.json b/frappe/website/doctype/website_settings/website_settings.json index 3469df560a..430c8b66ba 100644 --- a/frappe/website/doctype/website_settings/website_settings.json +++ b/frappe/website/doctype/website_settings/website_settings.json @@ -1,5 +1,6 @@ { "allow_copy": 0, + "allow_guest_to_view": 0, "allow_import": 0, "allow_rename": 0, "beta": 0, @@ -21,6 +22,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Landing Page", @@ -49,6 +51,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 1, "in_standard_filter": 0, "label": "Home Page", @@ -77,6 +80,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "length": 0, @@ -104,6 +108,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 1, "in_standard_filter": 0, "label": "Title Prefix", @@ -131,6 +136,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "length": 0, @@ -159,6 +165,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Website Theme", @@ -188,6 +195,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Website Theme Image", @@ -217,6 +225,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Website Theme Image Link", @@ -245,6 +254,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Brand", @@ -274,6 +284,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Brand Image", @@ -303,6 +314,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Brand HTML", @@ -330,6 +342,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Set Banner from Image", @@ -358,6 +371,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Top Bar", @@ -374,6 +388,35 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "navbar_search", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Include Search in Top Bar", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "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 + }, { "allow_on_submit": 0, "bold": 0, @@ -385,6 +428,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Top Bar Items", @@ -414,6 +458,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Banner", @@ -442,6 +487,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Banner HTML", @@ -469,6 +515,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Footer", @@ -496,6 +543,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Copyright", @@ -524,6 +572,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Address", @@ -551,6 +600,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Footer Items", @@ -579,6 +629,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Hide Footer Signup", @@ -607,6 +658,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Integrations", @@ -635,6 +687,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Google Analytics ID", @@ -662,6 +715,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "length": 0, @@ -688,6 +742,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "More Information", @@ -716,6 +771,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "FavIcon", @@ -745,6 +801,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Subdomain", @@ -772,6 +829,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "length": 0, @@ -799,6 +857,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Disable Signup", @@ -826,6 +885,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "HTML Header & Robots", @@ -855,6 +915,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "<head> HTML", @@ -884,6 +945,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Robots.txt", @@ -902,18 +964,18 @@ "unique": 0 } ], + "has_web_view": 0, "hide_heading": 0, "hide_toolbar": 0, "icon": "fa fa-cog", "idx": 1, "image_view": 0, "in_create": 0, - "in_dialog": 0, "is_submittable": 0, "issingle": 1, "istable": 0, "max_attachments": 10, - "modified": "2016-12-29 14:40:31.225882", + "modified": "2017-03-07 14:45:46.127265", "modified_by": "Administrator", "module": "Website", "name": "Website Settings", @@ -929,7 +991,6 @@ "export": 0, "if_owner": 0, "import": 0, - "is_custom": 0, "permlevel": 0, "print": 1, "read": 1, @@ -950,7 +1011,6 @@ "export": 0, "if_owner": 0, "import": 0, - "is_custom": 0, "permlevel": 1, "print": 0, "read": 1, @@ -965,6 +1025,7 @@ "quick_entry": 0, "read_only": 0, "read_only_onload": 0, + "show_name_in_global_search": 0, "sort_order": "ASC", "track_changes": 1, "track_seen": 0 diff --git a/frappe/website/router.py b/frappe/website/router.py index f0bf58a9da..ecf206342f 100644 --- a/frappe/website/router.py +++ b/frappe/website/router.py @@ -326,4 +326,48 @@ def get_doctypes_with_web_view(): dict(has_web_view=1)) if frappe.local.module_app[frappe.scrub(d.module)] in installed_apps] return doctypes - return frappe.cache().get_value('doctypes_with_web_view', _get) \ No newline at end of file + return frappe.cache().get_value('doctypes_with_web_view', _get) + +def sync_global_search(): + '''Sync page content in global search''' + from frappe.website.render import render_page + from frappe.utils.global_search import sync_global_search + from bs4 import BeautifulSoup + + frappe.flags.update_global_search = [] + frappe.session.user = 'Guest' + frappe.local.no_cache = True + + frappe.db.sql('delete from __global_search where doctype="Static Web Page"') + + for app in frappe.get_installed_apps(frappe_last=True): + app_path = frappe.get_app_path(app) + + folders = frappe.local.flags.web_pages_folders or ('www', 'templates/pages') + + for start in folders: + for basepath, folders, files in os.walk(os.path.join(app_path, start)): + for f in files: + if f.endswith('.html') or f.endswith('.md'): + path = os.path.join(basepath, f.rsplit('.', 1)[0]) + try: + content = render_page(path) + soup = BeautifulSoup(content, 'html.parser') + text = '' + route = os.path.relpath(path, os.path.join(app_path, start)) + for div in soup.findAll("div", {'class':'page-content'}): + text += div.text + + frappe.flags.update_global_search.append( + dict(doctype='Static Web Page', + name=route, + content=text, + published=1, + title=soup.title.string, + route=route)) + + except Exception: + pass + + sync_global_search() + diff --git a/frappe/www/search.css b/frappe/www/search.css new file mode 100644 index 0000000000..912a6602af --- /dev/null +++ b/frappe/www/search.css @@ -0,0 +1,7 @@ +.search-result { + margin-top: 30px; +} + +.search-result-item { + padding-bottom: 15px; +} \ No newline at end of file diff --git a/frappe/www/search.html b/frappe/www/search.html new file mode 100644 index 0000000000..00804241e7 --- /dev/null +++ b/frappe/www/search.html @@ -0,0 +1,51 @@ +{% extends "templates/web.html" %} + +{% block page_content %} +

    {{ title }}

    + +
    +
    + + +
    +
    + +{% if results %} + +
    + {% include "templates/includes/search_result.html" %} +
    + + {% if has_more %} + + {% endif %} + +{% elif frappe.form_dict.q %} +

    {{ _("No matching records. Search something new") }} +{% else %} +

    {{ _("Type something in the search box to search") }} +{% endif %} + + +{% endblock %} diff --git a/frappe/www/search.py b/frappe/www/search.py new file mode 100644 index 0000000000..d9027da77c --- /dev/null +++ b/frappe/www/search.py @@ -0,0 +1,47 @@ +from __future__ import unicode_literals +import frappe +from frappe.utils.global_search import web_search +from html2text import html2text +from frappe import _ + +def get_context(context): + context.no_cache = 1 + if frappe.form_dict.q: + context.title = _('Search Results for "{0}"').format(frappe.form_dict.q) + context.update(get_search_results(frappe.form_dict.q)) + else: + context.title = _('Search') + +@frappe.whitelist(allow_guest = True) +def get_search_results(text, start=0, as_html=False): + results = web_search(text, start, limit=21) + out = frappe._dict() + + if len(results) == 21: + out.has_more = 1 + results = results[:20] + + for d in results: + d.content = html2text(d.content) + index = d.content.lower().index(text.lower()) + d.content = d.content[:index] + '' + d.content[index:][:len(text)] + '' + d.content[index + len(text):] + + if index < 40: + start = 0 + prefix = '' + else: + start = index - 40 + prefix = '...' + + suffix = '' + if (index + len(text) + 47) < len(d.content): + suffix = '...' + + d.preview = prefix + d.content[start:start + len(text) + 87] + suffix + + out.results = results + + if as_html: + out.results = frappe.render_template('templates/includes/search_result.html', out) + + return out