@@ -1,4 +1,6 @@ | |||
## frappe [](https://travis-ci.org/frappe/frappe) | |||
## Frappe Framework | |||
[](https://travis-ci.org/frappe/frappe) | |||
Full-stack web application framework that uses Python and MariaDB on the server side and a tightly integrated client side library. [Built for ERPNext](https://erpnext.com) | |||
@@ -350,9 +350,28 @@ def build_website(context): | |||
finally: | |||
frappe.destroy() | |||
@click.command('setup-docs') | |||
@click.command('build-dev-docs') | |||
@pass_context | |||
def setup_docs(context): | |||
@click.argument('app') | |||
@click.argument('docs_version') | |||
def make_dev_docs(context, app, docs_version): | |||
"Setup docs in target folder of target app" | |||
from frappe.utils.setup_docs import setup_docs | |||
from frappe.website import statics | |||
for site in context.sites: | |||
try: | |||
frappe.init(site=site) | |||
frappe.connect() | |||
make = setup_docs(app) | |||
make.build(docs_version) | |||
finally: | |||
frappe.destroy() | |||
@click.command('make-docs') | |||
@pass_context | |||
@click.argument('app') | |||
@click.argument('target') | |||
def setup_docs(context, app, target): | |||
"Setup docs in target folder of target app" | |||
from frappe.utils.setup_docs import setup_docs | |||
from frappe.website import statics | |||
@@ -360,7 +379,8 @@ def setup_docs(context): | |||
try: | |||
frappe.init(site=site) | |||
frappe.connect() | |||
setup_docs() | |||
make = setup_docs(app) | |||
make.make_docs(target) | |||
statics.sync_statics(rebuild=True) | |||
finally: | |||
frappe.destroy() | |||
@@ -2,6 +2,7 @@ from __future__ import unicode_literals | |||
app_name = "frappe" | |||
app_title = "Frappe Framework" | |||
app_publisher = "Frappe Technologies Pvt. Ltd." | |||
app_short_description = "Full stack web framework with Python, Javascript, MariaDB, Redis, Node" | |||
app_description = """## Frappe Framework | |||
Frappe is a full stack web application framework written in Python, | |||
@@ -0,0 +1,105 @@ | |||
<!DOCTYPE html> | |||
<!-- Built on Frappe. https://frappe.io/ --> | |||
<html lang="en"> | |||
<head> | |||
<meta charset="utf-8"> | |||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |||
<title>{{ title }}</title> | |||
<meta name="generator" content="frappe"> | |||
<link type="text/css" rel="stylesheet" href="/assets/css/bootstrap.css"> | |||
<script type="text/javascript" src="/assets/js/jquery.min.js"></script> | |||
<script type="text/javascript" src="/assets/js/bootstrap.min.js"></script> | |||
{% block favicon %} | |||
<link rel="shortcut icon" | |||
href="{{ (favicon or "/assets/img/favicon.png") | abs_url }}" | |||
type="image/x-icon"> | |||
<link rel="icon" | |||
href="{{ (favicon or "/assets/img/favicon.png") | abs_url }}" | |||
type="image/x-icon"> | |||
{% endblock %} | |||
{%- block head -%} | |||
{% if meta_block is defined -%} | |||
{{ meta_block }} | |||
{%- endif %} | |||
{% if head_html is defined -%} | |||
{{ head_html or "" }} | |||
{%- endif %} | |||
{%- block head_include %}{{ head_include or "" }}{% endblock -%} | |||
{%- block style %} | |||
<style data-html-block="style"> | |||
{%- if style is defined -%}{{ style }}{%- endif -%} | |||
</style> | |||
{%- endblock -%} | |||
{%- endblock -%} | |||
{%- if js_globals is defined %} | |||
<script> | |||
{%- for key, value in js_globals.iteritems() %} | |||
window.{{ key }} = "{{ value[0] }}"; | |||
{%- endfor -%} | |||
</script> | |||
{% endif -%} | |||
</head> | |||
<body data-path="{{ path }}"> | |||
<div class="offcanvas-container"> | |||
<div class="offcanvas"> | |||
<div class="offcanvas-main-section"> | |||
<div> | |||
{%- block banner -%} | |||
{% include "templates/includes/banner_extension.html" ignore missing %} | |||
{% if banner_html -%} | |||
<header class="container">{{ banner_html or "" }}</header> | |||
{%- endif %} | |||
{%- endblock -%} | |||
{%- block navbar -%} | |||
{% include "templates/includes/navbar/navbar.html" %} | |||
{%- endblock -%} | |||
<div class="hero-and-content"> | |||
{%- block hero -%} | |||
<div data-html-block="hero"> | |||
{{ hero or "" }} | |||
</div> | |||
{%- endblock -%} | |||
{% block content %} | |||
<div class="container" data-html-block="content"> | |||
{{ content }} | |||
</div> | |||
{% endblock %} | |||
</div> | |||
<footer class="page-footer"> | |||
<div class="container" data-html-block="footer"> | |||
{%- if footer is defined -%}{{ footer }}{%- endif -%} | |||
</div> | |||
</footer> | |||
</div> | |||
<div> | |||
{%- block footer -%}{% include "templates/includes/footer/footer.html" %}{%- endblock -%} | |||
</div> | |||
</div> | |||
<div class="modal-backdrop offcanvas-main-section-overlay"></div> | |||
<div class="sidebar sidebar-right visible-xs"> | |||
{% block offcanvas_sidebar -%} | |||
<div class="sidebar-navbar-items"> | |||
{% include "templates/includes/navbar/navbar_items.html" %} | |||
</div> | |||
{%- endblock %} | |||
</div> | |||
</div> | |||
</div> | |||
<!-- js should be loaded in body! --> | |||
{%- block script %} | |||
<script data-html-block="script"> | |||
{%- if script is defined -%}{{ script }}{%- endif -%} | |||
</script> | |||
{%- endblock %} | |||
<!-- csrf_token --> | |||
{%- block body_include %}{{ body_include or "" }}{% endblock -%} | |||
</body> | |||
</html> |
@@ -53,7 +53,7 @@ def get_version(name): | |||
installed = frappe.get_installed_apps() | |||
def _for_module(m): | |||
return importlib.import_module(m.split(".")[0]).__version__ | |||
return getattr(importlib.import_module(m.split(".")[0]), "__version__", "0.0.0") | |||
if "." in name or name in installed: | |||
return _for_module(name) | |||
@@ -2,29 +2,41 @@ | |||
Call from command line: | |||
bench setup-docs app docs_app path | |||
bench setup-docs app path | |||
""" | |||
import os, json, frappe, markdown2, shutil | |||
import frappe.website.statics | |||
from frappe.website.context import get_context | |||
class setup_docs(object): | |||
def __init__(self): | |||
def __init__(self, app, docs_version, target): | |||
"""Generate source templates for models reference and module API | |||
and templates at `templates/autodoc` | |||
""" | |||
self.app = frappe.get_hooks("autodoc").get("for_app")[0] | |||
docs_app = frappe.get_hooks("autodoc").get("docs_app")[0] | |||
self.app = app | |||
self.path = frappe.get_app_path(app, "docs", docs_version) | |||
self.target = target | |||
# build apis | |||
# self.build() | |||
# sync docs | |||
sync = frappe.website.statics.sync() | |||
sync.start(path="docs", rebuild=True) | |||
# write in target path | |||
self.write_files() | |||
def build(self): | |||
hooks = frappe.get_hooks(app_name = self.app) | |||
self.app_title = hooks.get("app_title")[0] | |||
self.app_path = frappe.get_app_path(self.app) | |||
path = frappe.get_app_path(docs_app, "www", "current") | |||
print "Deleting current..." | |||
shutil.rmtree(path, ignore_errors = True) | |||
os.makedirs(path) | |||
shutil.rmtree(self.path, ignore_errors = True) | |||
os.makedirs(self.path) | |||
self.app_context = { | |||
"app": { | |||
@@ -38,16 +50,16 @@ class setup_docs(object): | |||
} | |||
# make home page | |||
with open(os.path.join(path, "index.html"), "w") as home: | |||
with open(os.path.join(self.path, "index.html"), "w") as home: | |||
home.write(frappe.render_template("templates/autodoc/docs_home.html", | |||
self.app_context)) | |||
# make folders | |||
self.models_base_path = os.path.join(path, "models") | |||
self.models_base_path = os.path.join(self.path, "models") | |||
self.make_folder(self.models_base_path, | |||
template = "templates/autodoc/models_home.html") | |||
self.api_base_path = os.path.join(path, "api") | |||
self.api_base_path = os.path.join(self.path, "api") | |||
self.make_folder(self.api_base_path, | |||
template = "templates/autodoc/api_home.html") | |||
@@ -164,3 +176,29 @@ class setup_docs(object): | |||
context.update(self.app_context) | |||
f.write(frappe.render_template("templates/autodoc/doctype.html", | |||
context).encode("utf-8")) | |||
def write_files(self): | |||
frappe.local.flags.home_page = "index" | |||
for page in frappe.db.sql("""select parent_website_route, | |||
page_name from `tabWeb Page`""", as_dict=True): | |||
if page.parent_website_route: | |||
path = page.parent_website_route + "/" + page.page_name | |||
else: | |||
path = page.page_name | |||
frappe.local.path = path | |||
context = get_context(path) | |||
html = frappe.get_template(context.base_template_path).render(context) | |||
target_filename = os.path.join(self.target, context.template_path.split('/docs/')[1]) | |||
if not os.path.exists(os.path.dirname(target_filename)): | |||
os.makedirs(os.path.dirname(target_filename)) | |||
with open(target_filename, "w") as htmlfile: | |||
htmlfile.write(html.encode("utf-8")) | |||
print "wrote {0}".format(target_filename) |
@@ -136,7 +136,6 @@ def build_page(path): | |||
frappe.local.path = path | |||
context = get_context(path) | |||
html = frappe.get_template(context.base_template_path).render(context) | |||
if can_cache(context.no_cache): | |||
@@ -17,10 +17,11 @@ def sync_statics(rebuild=False): | |||
# rebuild = False | |||
class sync(object): | |||
def __init__(self, verbose=False): | |||
def __init__(self, verbose=False, path=None): | |||
self.verbose = verbose | |||
def start(self, rebuild=False): | |||
def start(self, rebuild=False, path="www"): | |||
self.path = path | |||
self.synced = [] | |||
self.synced_paths = [] | |||
self.updated = 0 | |||
@@ -33,7 +34,7 @@ class sync(object): | |||
self.cleanup() | |||
def sync_for_app(self, app): | |||
self.statics_path = frappe.get_app_path(app, "www") | |||
self.statics_path = frappe.get_app_path(app, self.path) | |||
if os.path.exists(self.statics_path): | |||
for basepath, folders, files in os.walk(self.statics_path): | |||
self.sync_folder(basepath, folders, files, app) | |||
@@ -3,7 +3,6 @@ | |||
from __future__ import unicode_literals | |||
import frappe, re, os | |||
from werkzeug.urls import url_parse, url_unparse | |||
def delete_page_cache(path): | |||
cache = frappe.cache() | |||
@@ -33,14 +32,18 @@ def get_comment_list(doctype, name): | |||
and comment_docname=%s order by creation""", (doctype, name), as_dict=1) or [] | |||
def get_home_page(): | |||
if frappe.local.flags.home_page: | |||
return frappe.local.flags.home_page | |||
def _get_home_page(): | |||
role_home_page = frappe.get_hooks("role_home_page") | |||
home_page = None | |||
for role in frappe.get_roles(): | |||
if role in role_home_page: | |||
home_page = role_home_page[role][-1] | |||
break | |||
if role_home_page: | |||
for role in frappe.get_roles(): | |||
if role in role_home_page: | |||
home_page = role_home_page[role][-1] | |||
break | |||
if not home_page: | |||
home_page = frappe.get_hooks("home_page") | |||