@@ -1,7 +1,13 @@ | |||
### Custom DocTypes | |||
### Version 5 | |||
The user can add Custom DocTypes (Forms) without creating a new app by setting **Custom** property. | |||
Please see https://frappe.io/version-5 | |||
### Site Configuration | |||
Changes include: | |||
1. New Visual Design | |||
1. Custom DocTypes | |||
1. Email Accounts | |||
1. Email Replies and Notifications | |||
1. Print Format Builder | |||
1. Document Sharing | |||
- Stop multiple logins for a user by setting `deny_multiple_sessions` in `site_config.json`. [Help on `site_config.json`](https://frappe.io/docs/user-guide/site_config). |
@@ -6,8 +6,8 @@ | |||
height: 50px; | |||
} | |||
.avatar img { | |||
width: 100%; | |||
height: auto; | |||
max-width: 100%; | |||
max-height: 100%; | |||
border-radius: 4px; | |||
} | |||
.avatar-empty { | |||
@@ -225,8 +225,8 @@ body { | |||
height: 50px; | |||
} | |||
.avatar img { | |||
width: 100%; | |||
height: auto; | |||
max-width: 100%; | |||
max-height: 100%; | |||
border-radius: 4px; | |||
} | |||
.avatar-empty { | |||
@@ -455,6 +455,9 @@ fieldset { | |||
.page-sidebar .sidebar-item a { | |||
color: #8d99a6; | |||
} | |||
.page-sidebar .sidebar-item a:hover { | |||
border-color: inherit; | |||
} | |||
.page-sidebar .sidebar-item a.active { | |||
color: #000; | |||
font-weight: bold; | |||
@@ -519,6 +522,16 @@ textarea { | |||
.visible-xs { | |||
display: none !important; | |||
} | |||
.toggle-sidebar { | |||
margin-top: 8px; | |||
margin-right: 15px; | |||
} | |||
.sidebar-navbar-items a, | |||
.sidebar-navbar-items a:hover, | |||
.sidebar-navbar-items a:focus, | |||
.sidebar-navbar-items a:visited { | |||
border-bottom: 0px; | |||
} | |||
@media (max-width: 767px) { | |||
.visible-xs { | |||
display: inline-block !important; | |||
@@ -641,3 +654,40 @@ a.active { | |||
border-right: 1px solid #f2f2f2; | |||
} | |||
} | |||
.full-center-container { | |||
position: absolute; | |||
top: 0; | |||
bottom: 0; | |||
left: 0; | |||
right: 0; | |||
} | |||
.full-center { | |||
position: absolute; | |||
top: 50%; | |||
left: 50%; | |||
width: 100%; | |||
transform: translate(-50%, -50%); | |||
-webkit-transform: translate(-50%, -50%); | |||
} | |||
#freeze { | |||
z-index: 1020; | |||
bottom: 0px; | |||
background-color: #fafbfc; | |||
} | |||
#freeze .freeze-message-container { | |||
position: absolute; | |||
top: 0; | |||
bottom: 0; | |||
left: 0; | |||
right: 0; | |||
} | |||
#freeze .freeze-message { | |||
position: absolute; | |||
top: 50%; | |||
left: 50%; | |||
width: 100%; | |||
transform: translate(-50%, -50%); | |||
-webkit-transform: translate(-50%, -50%); | |||
text-align: center; | |||
color: #fff !important; | |||
} |
@@ -7,8 +7,8 @@ | |||
} | |||
.avatar img { | |||
width: 100%; | |||
height: auto; | |||
max-width: 100%; | |||
max-height: 100%; | |||
border-radius: 4px; | |||
} | |||
@@ -194,6 +194,10 @@ fieldset { | |||
color: @text-muted; | |||
} | |||
.sidebar-item a:hover { | |||
border-color: inherit; | |||
} | |||
.sidebar-item a.active { | |||
color: #000; | |||
font-weight: bold; | |||
@@ -272,6 +276,17 @@ textarea { | |||
display: none !important; | |||
} | |||
.toggle-sidebar { | |||
margin-top: 8px; | |||
margin-right: 15px; | |||
} | |||
.sidebar-navbar-items { | |||
a, a:hover, a:focus, a:visited { | |||
border-bottom: 0px; | |||
} | |||
} | |||
@media (max-width: 767px) { | |||
.visible-xs { | |||
display: inline-block !important; | |||
@@ -363,4 +378,37 @@ a.active { | |||
} | |||
} | |||
.full-center-container { | |||
position: absolute; | |||
top: 0; | |||
bottom: 0; | |||
left: 0; | |||
right: 0; | |||
} | |||
.full-center { | |||
position: absolute; | |||
top: 50%; | |||
left: 50%; | |||
width: 100%; | |||
transform: translate(-50%, -50%); | |||
-webkit-transform: translate(-50%, -50%); | |||
} | |||
#freeze { | |||
z-index: 1020; | |||
bottom: 0px; | |||
background-color: @light-bg; | |||
.freeze-message-container { | |||
.full-center-container; | |||
} | |||
.freeze-message { | |||
.full-center; | |||
text-align: center; | |||
color: #fff !important; | |||
} | |||
} | |||
@@ -1,7 +1,5 @@ | |||
<!DOCTYPE html> | |||
<!-- | |||
Built on Frappe.io. Free and Open Source Framework for the Web. https://frappe.io/ | |||
--> | |||
<!-- Built on Frappe. https://frappe.io/ --> | |||
<html lang="en"> | |||
<head> | |||
<meta charset="utf-8"> | |||
@@ -11,13 +9,14 @@ Built on Frappe.io. Free and Open Source Framework for the Web. https://frappe.i | |||
<script type="text/javascript" | |||
src="/assets/frappe/js/lib/jquery/jquery.min.js"></script> | |||
{% block favicon %} | |||
<link rel="shortcut icon" | |||
href="{{ favicon or "/assets/frappe/images/favicon.ico" }}" | |||
type="image/x-icon"> | |||
<link rel="icon" | |||
href="{{ favicon or "/assets/frappe/images/favicon.ico" }}" | |||
type="image/x-icon"> | |||
{%- block head_include %}{% endblock -%} | |||
{% endblock %} | |||
{%- block head -%} | |||
{% if meta_block is defined %} | |||
{{ meta_block }} | |||
@@ -36,6 +35,7 @@ Built on Frappe.io. Free and Open Source Framework for the Web. https://frappe.i | |||
{%- for link in web_include_js %} | |||
<script type="text/javascript" src="{{ link }}"></script> | |||
{%- endfor -%} | |||
{%- block head_include %}{% endblock -%} | |||
{%- endblock -%} | |||
</head> | |||
<body> | |||
@@ -51,29 +51,8 @@ Built on Frappe.io. Free and Open Source Framework for the Web. https://frappe.i | |||
{%- endblock -%} | |||
{%- block navbar -%}{% include "templates/includes/navbar/navbar.html" %}{%- endblock -%} | |||
<div class="container"> | |||
<div class="page-container" id="page-{{ name or page_name }}" data-path="{{ pathname }}"> | |||
<div class="row"> | |||
<div class="col-sm-10 col-xs-12 page-content"> | |||
<div class="page-header-block" data-html-block="header"> | |||
{%- if header is defined -%}{% if header %}{{ header }}{% endif %}{%- endif -%} | |||
</div> | |||
<div class="page-breadcrumbs" data-html-block="breadcrumbs"> | |||
{%- if breadcrumbs is defined -%}{{ breadcrumbs }}{%- endif -%} | |||
</div> | |||
<div class="page-content-block" data-html-block="content"> | |||
{%- block content -%}{{ content or "" }}{%- endblock -%} | |||
</div> | |||
</div> | |||
<div class="col-sm-2 hidden-xs page-sidebar" data-html-block="sidebar"> | |||
{%- block sidebar -%} | |||
{%- if sidebar is defined -%} | |||
{{ sidebar }} | |||
{%- endif -%} | |||
{%- endblock -%} | |||
</div> | |||
</div> | |||
</div> | |||
<div class="container" data-html-block="content"> | |||
{{ content }} | |||
</div> | |||
<footer class="page-footer"> | |||
<div class="container" data-html-block="footer"> | |||
@@ -13,28 +13,5 @@ | |||
{% include "templates/includes/navbar/navbar_link.html" %} | |||
{%- endif -%} | |||
{%- endfor %} | |||
<!-- post login tools --> | |||
<li class="dropdown logged-in" id="website-post-login" | |||
data-label="website-post-login" style="display: none"> | |||
<a href="#" class="dropdown-toggle" data-toggle="dropdown"> | |||
<span class="avatar avatar-small user-image-wrapper"><img class="user-image"/></span> | |||
<span class="visible-xs full-name"></span> | |||
</a> | |||
<ul class="dropdown-menu" role="menu"> | |||
{%- for child in post_login -%} | |||
<li {% if child.label %}data-label="{{ child.label }}" {% endif %} | |||
{% if child.class %} class="{{ child.class }}" {% endif %}> | |||
{%- if child.url -%} | |||
<a href="{{ child.url }}" {{ child.target or '' }} | |||
rel="nofollow"> | |||
{{ child.label }} | |||
</a> | |||
{%- endif -%} | |||
</li> | |||
{%- endfor -%} | |||
</ul> | |||
</li> | |||
<li class="btn-login-area"><a href="/login"> | |||
{%- if not disable_signup %}{{ _("Sign Up") }} / {% endif -%} {{ _("Login") }}</a></li> | |||
{% include "templates/includes/navbar/navbar_login.html" %} | |||
</ul> |
@@ -0,0 +1,25 @@ | |||
<!-- post login tools --> | |||
<li class="dropdown logged-in" id="website-post-login" | |||
data-label="website-post-login" style="display: none"> | |||
<a href="#" class="dropdown-toggle" data-toggle="dropdown"> | |||
<span class="avatar avatar-small user-image-wrapper" style="margin-top: -4px;"><img class="user-image"/></span> | |||
<span class="visible-xs full-name"></span> | |||
</a> | |||
<ul class="dropdown-menu" role="menu"> | |||
{%- for child in post_login -%} | |||
<li {% if child.label %}data-label="{{ child.label }}" {% endif %} | |||
{% if child.class %} class="{{ child.class }}" {% endif %}> | |||
{%- if child.url -%} | |||
<a href="{{ child.url }}" {{ child.target or '' }} | |||
rel="nofollow"> | |||
{{ child.label }} | |||
</a> | |||
{%- endif -%} | |||
</li> | |||
{%- endfor -%} | |||
</ul> | |||
</li> | |||
{% if not hide_login %} | |||
<li class="btn-login-area"><a href="/login">{{ _("Login") }}</a></li> | |||
{% endif %} |
@@ -0,0 +1,28 @@ | |||
{% macro inner() %} | |||
<div class="page-header-block" data-html-block="header"> | |||
{%- if header is defined -%}{% if header %}{{ header }}{% endif %}{%- endif -%} | |||
</div> | |||
<div class="page-breadcrumbs" data-html-block="breadcrumbs"> | |||
{%- if breadcrumbs is defined -%}{{ breadcrumbs }}{%- endif -%} | |||
</div> | |||
<div class="page-content-block"> | |||
{%- block content -%}{{ content or "" }}{%- endblock -%} | |||
</div> | |||
{% endmacro %} | |||
<div class="page-container" id="page-{{ name or page_name }}" data-path="{{ pathname }}"> | |||
<div class="row"> | |||
{% if has_sidebar %} | |||
<div class="col-sm-10 col-xs-12 page-content"> | |||
{{ inner() }} | |||
</div> | |||
<div class="col-sm-2 hidden-xs page-sidebar"> | |||
{%- block sidebar -%}{{ sidebar or "" }}{%- endblock -%} | |||
</div> | |||
{% else %} | |||
<div class="col-sm-12 page-content no-border"> | |||
{{ inner() }} | |||
</div> | |||
{% endif %} | |||
</div> | |||
</div> |
@@ -1,15 +1,12 @@ | |||
{%- block title -%}{{_("Not Found")}}{%- endblock -%} | |||
{%- block header -%} | |||
<h2 class="text-danger"><i class="icon-exclamation-sign"></i> {{_("Page missing or moved")}}</h2> | |||
<h1 class="text-danger" style="margin-top: 100px;">{{_("Page missing or moved")}}</h1> | |||
{%- endblock -%} | |||
{% block content %} | |||
<div class="404-content"> | |||
<div class="panel panel-default"> | |||
<div class="panel-body"> | |||
<p>{{_("We are very sorry for this, but the page you are looking for is missing (this could be because of a typo in the address) or moved.")}}</p> | |||
</div> | |||
</div> | |||
<!-- no-sidebar --> | |||
<div class="404-content" style="margin-bottom: 100px;"> | |||
<p>{{_("We are very sorry for this, but the page you are looking for is missing (this could be because of a typo in the address) or moved.")}}</p> | |||
</div> | |||
{% endblock %} | |||
{% endblock %} |
@@ -7,6 +7,7 @@ | |||
{% endblock %} | |||
{% block content %} | |||
<!-- no-sidebar --> | |||
<div class="error-content"> | |||
<pre><code>{{ error }}</code></pre> | |||
</div> | |||
@@ -2,6 +2,7 @@ | |||
{% block content %} | |||
<!-- no-header --> | |||
<!-- no-sidebar --> | |||
<div class="login-content container" style="max-width: 800px; padding-top: 30px; padding-bottom:15px"> | |||
<form class="form-signin form-login" role="form"> | |||
{%- if social_login -%} | |||
@@ -2,17 +2,18 @@ | |||
{% block content %} | |||
<!-- no-header --> | |||
<!-- no-sidebar --> | |||
<div class="row"> | |||
<div class="col-sm-3"> | |||
<div class="your-account-info"> | |||
<div class="avatar avatar-large"> | |||
<a href="/user"><img class="user-image" src="{{ user_image }}" /></a> | |||
<a href="/me"><img class="user-image" src="{{ user_image }}" /></a> | |||
</div> | |||
<div> | |||
<h4><a href="/user">{{ fullname }}</a></h4> | |||
<h4><a href="/me">{{ fullname }}</a></h4> | |||
<ul class="list-unstyled small user-options"> | |||
<li><a href="">{{ _("Reset Password") }}</a></li> | |||
<li><a href="">{{ _("Logout") }}</a></li> | |||
<li><a href="/update-password">{{ _("Reset Password") }}</a></li> | |||
<li><a href="/?cmd=web_logout">{{ _("Logout") }}</a></li> | |||
</ul> | |||
</div> | |||
</div> | |||
@@ -3,6 +3,7 @@ | |||
{% block header %}{{ title }}{% endblock %} | |||
{% block content %} | |||
<!-- no-sidebar --> | |||
<div class="message-content"> | |||
<div> | |||
{{ message }} | |||
@@ -4,6 +4,7 @@ | |||
{% block breadcrumbs %}{% endblock %} | |||
{% block content %} | |||
<!-- no-sidebar --> | |||
<div class="container"> | |||
<div class="row" style="margin-top: 40px; margin-bottom: 20px"> | |||
<div class="col-sm-offset-3 col-sm-6"> | |||
@@ -80,15 +80,17 @@ def before_tests(): | |||
def import_country_and_currency(): | |||
from frappe.geo.country_info import get_all | |||
print "Importing Geo..." | |||
from frappe.utils import update_progress_bar | |||
data = get_all() | |||
for name in data: | |||
for i, name in enumerate(data): | |||
update_progress_bar("Updating country info", i, len(data)) | |||
country = frappe._dict(data[name]) | |||
add_country_and_currency(name, country) | |||
# enable frequently used currencies | |||
for currency in ("INR", "USD", "GBP", "EUR", "AED", "AUD", "JPY", "CNY", "CHF"): | |||
frappe.db.set_value("Currency", currency, "enabled", 1) | |||
@@ -42,7 +42,6 @@ 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(context) | |||
context.update(get_website_settings()) | |||
context.update(frappe.get_hooks("website_context") or {}) | |||
context.update(frappe.local.conf.get("website_context") or {}) | |||
# provide doc | |||
@@ -122,5 +122,11 @@ def get_website_settings(): | |||
add_website_theme(context) | |||
via_hooks = frappe.get_hooks("website_context") | |||
for key in via_hooks: | |||
context[key] = via_hooks[key] | |||
if key not in ("top_bar_items", "footer_items", "post_login"): | |||
context[key] = context[key][0] | |||
return context | |||
@@ -261,7 +261,7 @@ $.extend(frappe, { | |||
if (last_part.indexOf(".")!==-1 && (last_part.indexOf(".htm")===-1)) | |||
return; | |||
event.preventDefault() | |||
event.preventDefault(); | |||
frappe.load_via_ajax(link.href); | |||
}, | |||
@@ -281,6 +281,7 @@ $.extend(frappe, { | |||
frappe.render_json(data); | |||
}; | |||
frappe.freeze(); | |||
$.ajax({ | |||
url: href, | |||
cache: false, | |||
@@ -290,6 +291,8 @@ $.extend(frappe, { | |||
} | |||
}).fail(function(xhr, status, error) { | |||
window.location.reload(); | |||
}).always(function() { | |||
frappe.unfreeze(); | |||
}); | |||
}, | |||
render_json: function(data) { | |||
@@ -357,6 +360,40 @@ $.extend(frappe, { | |||
} | |||
frappe.page_ready_events[frappe.get_pathname()].push(fn); | |||
}, | |||
freeze_count: 0, | |||
freeze: function(msg) { | |||
// blur | |||
if(!$('#freeze').length) { | |||
var freeze = $('<div id="freeze" class="modal-backdrop fade"></div>') | |||
.on("click", function() { | |||
if (cur_frm && cur_frm.cur_grid) { | |||
cur_frm.cur_grid.toggle_view(); | |||
return false; | |||
} | |||
}) | |||
.appendTo("body"); | |||
freeze.html(repl('<div class="freeze-message-container"><div class="freeze-message">%(msg)s</div></div>', | |||
{msg: msg || ""})); | |||
setTimeout(function() { freeze.addClass("in") }, 1); | |||
} else { | |||
$("#freeze").addClass("in"); | |||
} | |||
frappe.freeze_count++; | |||
}, | |||
unfreeze: function() { | |||
if(!frappe.freeze_count) return; // anything open? | |||
frappe.freeze_count--; | |||
if(!frappe.freeze_count) { | |||
var freeze = $('#freeze').removeClass("in"); | |||
setTimeout(function() { | |||
if(!frappe.freeze_count) { freeze.remove(); } | |||
}, 150); | |||
} | |||
}, | |||
trigger_ready: function() { | |||
var ready_functions = frappe.page_ready_events[frappe.get_pathname()]; | |||
if (ready_functions && ready_functions.length) { | |||
@@ -420,29 +457,6 @@ $.extend(frappe, { | |||
$("[data-html-block='breadcrumbs'] .breadcrumb").toggleClass("hidden", | |||
!$("[data-html-block='breadcrumbs']").text().trim() || | |||
$("[data-html-block='breadcrumbs']").text().trim()==$("[data-html-block='header']").text().trim()); | |||
// to show full content width, when no sidebar content | |||
var sidebar_content = $("[data-html-block='sidebar']").html(), | |||
sidebar_has_content = sidebar_content ? !!sidebar_content.trim() : false; | |||
// hide sidebar if no content | |||
$(".page-sidebar, .toggle-sidebar").toggleClass("hide", !sidebar_has_content); | |||
// push sidebar to the right if there is content | |||
// $(".page-sidebar").toggleClass("col-sm-push-" + frappe.page_cols, sidebar_has_content); | |||
// make page content wide if no sidebar | |||
$(".page-content").toggleClass("col-sm-12", !sidebar_has_content); | |||
// narrow page content if sidebar | |||
$(".page-content").toggleClass("col-sm-"+frappe.page_cols, sidebar_has_content); | |||
// no borders if no sidebars | |||
$(".page-content").toggleClass("no-border", !sidebar_has_content); | |||
// if everything in the sub-header is hidden, hide the sub-header | |||
// var hide_sub_header = $(".page-sub-header .row").children().length === $(".page-sub-header .row").find(".hidden").length; | |||
// $(".page-sub-header").toggleClass("hidden", hide_sub_header); | |||
} | |||
}); | |||
@@ -627,8 +641,6 @@ $(document).ready(function() { | |||
$(document).on("page-change", function() { | |||
$(document).trigger("apply_permissions"); | |||
frappe.datetime.refresh_when(); | |||
frappe.sidebar_cols = $(".page-sidebar").hasClass("col-sm-3") ? 3 : 2; | |||
frappe.page_cols = 12 - frappe.sidebar_cols; | |||
frappe.toggle_template_blocks(); | |||
frappe.trigger_ready(); | |||
frappe.bind_filters(); | |||
@@ -2,7 +2,7 @@ | |||
# MIT License. See license.txt | |||
from __future__ import unicode_literals | |||
import frappe, os, time | |||
import frappe, os | |||
def sync_statics(rebuild=False): | |||
s = sync() | |||
@@ -28,6 +28,7 @@ class sync(object): | |||
frappe.db.sql("delete from `tabWeb Page` where ifnull(template_path, '')!=''") | |||
for app in frappe.get_installed_apps(): | |||
print app | |||
self.sync_for_app(app) | |||
self.cleanup() | |||
@@ -31,8 +31,12 @@ def render_blocks(context): | |||
_render_blocks(context["template"]) | |||
out["has_sidebar"] = not (context.get("no_sidebar", 0) or ("<!-- no-sidebar -->" in out.get("content", ""))) | |||
if out.get("has_sidebar"): | |||
out["sidebar"] = frappe.get_template("templates/includes/sidebar.html").render(context) | |||
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 | |||
@@ -68,11 +72,6 @@ def render_blocks(context): | |||
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) | |||
@@ -96,4 +95,7 @@ def render_blocks(context): | |||
out["style"] = re.sub("</?style[^<>]*>", "", out.get("style") or "") | |||
out["script"] = re.sub("</?script[^<>]*>", "", out.get("script") or "") | |||
# render | |||
out["content"] = frappe.get_template("templates/includes/page_content.html").render(out) | |||
return out |