@@ -12,6 +12,7 @@ frappe.ui.form.Dashboard = Class.extend({ | |||||
this.heatmap_area = this.wrapper.find('.form-heatmap'); | this.heatmap_area = this.wrapper.find('.form-heatmap'); | ||||
this.chart_area = this.wrapper.find('.form-chart'); | this.chart_area = this.wrapper.find('.form-chart'); | ||||
this.stats_area = this.wrapper.find('.form-stats'); | this.stats_area = this.wrapper.find('.form-stats'); | ||||
this.stats_area_row = this.stats_area.find('.row'); | |||||
this.links_area = this.wrapper.find('.form-links'); | this.links_area = this.wrapper.find('.form-links'); | ||||
this.transactions_area = this.links_area.find('.transactions'); | this.transactions_area = this.links_area.find('.transactions'); | ||||
@@ -28,7 +29,8 @@ frappe.ui.form.Dashboard = Class.extend({ | |||||
this.links_area.find('.count, .open-notification').addClass('hidden'); | this.links_area.find('.count, .open-notification').addClass('hidden'); | ||||
// clear stats | // clear stats | ||||
this.stats_area.empty().addClass('hidden'); | |||||
this.stats_area.addClass('hidden') | |||||
this.stats_area_row.empty(); | |||||
// clear custom | // clear custom | ||||
this.wrapper.find('.custom').remove(); | this.wrapper.find('.custom').remove(); | ||||
@@ -345,8 +347,9 @@ frappe.ui.form.Dashboard = Class.extend({ | |||||
this.show(); | this.show(); | ||||
this.stats_area.removeClass('hidden'); | this.stats_area.removeClass('hidden'); | ||||
// set colspan | // set colspan | ||||
var indicators = this.stats_area.find('.indicator-column'); | |||||
var indicators = this.stats_area_row.find('.indicator-column'); | |||||
var n_indicators = indicators.length + 1; | var n_indicators = indicators.length + 1; | ||||
if(n_indicators > 4) { colspan = 3 } | if(n_indicators > 4) { colspan = 3 } | ||||
else { colspan = 12 / n_indicators; } | else { colspan = 12 / n_indicators; } | ||||
@@ -357,7 +360,7 @@ frappe.ui.form.Dashboard = Class.extend({ | |||||
} | } | ||||
var indicator = $('<div class="col-sm-'+colspan+' indicator-column"><span class="indicator '+color+'">' | var indicator = $('<div class="col-sm-'+colspan+' indicator-column"><span class="indicator '+color+'">' | ||||
+label+'</span></div>').appendTo(this.stats_area); | |||||
+label+'</span></div>').appendTo(this.stats_area_row); | |||||
return indicator; | return indicator; | ||||
}, | }, | ||||
@@ -8,7 +8,9 @@ | |||||
<div class="text-muted small heatmap-message hidden"></div> | <div class="text-muted small heatmap-message hidden"></div> | ||||
</div> | </div> | ||||
<div class="form-chart form-dashboard-section hidden"></div> | <div class="form-chart form-dashboard-section hidden"></div> | ||||
<div class="form-stats form-dashboard-section hidden row"></div> | |||||
<div class="form-stats form-dashboard-section hidden"> | |||||
<div class="row"></div> | |||||
</div> | |||||
<div class="form-links form-dashboard-section hidden"> | <div class="form-links form-dashboard-section hidden"> | ||||
<div class="transactions"></div> | <div class="transactions"></div> | ||||
</div> | </div> |
@@ -58,7 +58,7 @@ | |||||
data-label="{{ _(field.label) }}" data-fieldtype="{{ field.fieldtype }}" | data-label="{{ _(field.label) }}" data-fieldtype="{{ field.fieldtype }}" | ||||
data-doctype="{{ field.parent }}" data-default="{{ field.default or "" }}" | data-doctype="{{ field.parent }}" data-default="{{ field.default or "" }}" | ||||
{{ (field.reqd and field.fieldtype!="Attach") and "data-reqd=1" or "" }} | {{ (field.reqd and field.fieldtype!="Attach") and "data-reqd=1" or "" }} | ||||
{{ field.read_only and "disabled" or "" }} | |||||
{{ (read_only or field.read_only) and "disabled" or "" }} | |||||
{% endmacro -%} | {% endmacro -%} | ||||
{%- macro value(field, _doc) -%} | {%- macro value(field, _doc) -%} | ||||
@@ -96,7 +96,6 @@ | |||||
class="form-control" {{ properties(field) }} | class="form-control" {{ properties(field) }} | ||||
value="{{ value(field, _doc) }}" | value="{{ value(field, _doc) }}" | ||||
{%- if field.fieldtype=="Int" %} pattern="[0-9]*"{% endif %} | {%- if field.fieldtype=="Int" %} pattern="[0-9]*"{% endif %} | ||||
{%- if field.max_value %} max={{ field.max_value }}{% endif %} | |||||
{%- if field.max_length %} maxlength={{ field.max_length }}{% endif %}> | {%- if field.max_length %} maxlength={{ field.max_length }}{% endif %}> | ||||
{{ help(field) }} | {{ help(field) }} | ||||
</div> | </div> | ||||
@@ -264,7 +263,7 @@ | |||||
<div class='text-muted' style='padding-bottom: 15px;'> | <div class='text-muted' style='padding-bottom: 15px;'> | ||||
{{ payment_button_help }}</div> | {{ payment_button_help }}</div> | ||||
{% endif %} | {% endif %} | ||||
<a class="btn btn-primary" href="{{ payment_url }}"> | |||||
<a class="btn btn-primary btn-payment" href="{{ payment_url }}"> | |||||
{{ payment_button_label }}</a> | {{ payment_button_label }}</a> | ||||
{% else %} | {% else %} | ||||
<div>{{ _("Payment Complete") }}</div> | <div>{{ _("Payment Complete") }}</div> | ||||
@@ -321,6 +320,7 @@ frappe.ready(function() { | |||||
frappe.form_dirty = false; | frappe.form_dirty = false; | ||||
frappe.max_attachment_size = {{ max_attachment_size }}; | frappe.max_attachment_size = {{ max_attachment_size }}; | ||||
moment.defaultFormat = "{{ frappe.date_format.upper() }}"; | moment.defaultFormat = "{{ frappe.date_format.upper() }}"; | ||||
{% if row_template %}frappe.web_form_row_template = "{{ row_template }}";{% endif %} | |||||
var $form = $("form[data-web-form='{{ name }}']"); | var $form = $("form[data-web-form='{{ name }}']"); | ||||
@@ -370,6 +370,12 @@ frappe.ready(function() { | |||||
set_mandatory_class(this); | set_mandatory_class(this); | ||||
}).on('keypress', function() { | }).on('keypress', function() { | ||||
set_mandatory_class(this); | set_mandatory_class(this); | ||||
// validate maxlength | |||||
var maxlength = parseInt($(this).attr('maxlength')); | |||||
if(maxlength && (($(this).val() || '') + '').length > maxlength-1) { | |||||
$(this).val($(this).val().substr(0, maxlength-1)); | |||||
}; | |||||
}).each(function() { set_mandatory_class(this); }); | }).each(function() { set_mandatory_class(this); }); | ||||
// if changed, set dirty flag | // if changed, set dirty flag | ||||
@@ -377,6 +383,16 @@ frappe.ready(function() { | |||||
frappe.form_dirty = true; | frappe.form_dirty = true; | ||||
}); | }); | ||||
// allow payment only if | |||||
$('.btn-payment').on('click', function() { | |||||
var data = get_data(); | |||||
if(frappe.mandatory_missing.length) { | |||||
frappe.msgprint(__('Payment can only be made after filling the following mandatory fields: {0}', | |||||
['<br><br><ol><li>' + frappe.mandatory_missing.join('<li>') + '</ol>'])); | |||||
return false; | |||||
} | |||||
}); | |||||
// change attach | // change attach | ||||
$form.on("click", ".change-attach", function() { | $form.on("click", ".change-attach", function() { | ||||
$(this).parent().addClass("hide") | $(this).parent().addClass("hide") | ||||
@@ -10,9 +10,10 @@ frappe.ready(function() { | |||||
txt: "{{ txt or '' }}", | txt: "{{ txt or '' }}", | ||||
limit_start: next_start, | limit_start: next_start, | ||||
pathname: location.pathname, | pathname: location.pathname, | ||||
is_web_form: "{{ is_web_form }}" | |||||
}); | }); | ||||
data.web_form_name = frappe.web_form_name; | |||||
btn.prop("disabled", true); | btn.prop("disabled", true); | ||||
return $.ajax({ | return $.ajax({ | ||||
url:"/api/method/frappe.www.list.get", | url:"/api/method/frappe.www.list.get", | ||||
@@ -37,7 +38,7 @@ frappe.ready(function() { | |||||
$(".website-list .more-block").addClass("hide"); | $(".website-list .more-block").addClass("hide"); | ||||
} | } | ||||
}; | }; | ||||
if($('.navbar-header .navbar-toggle:visible').length === 1) | if($('.navbar-header .navbar-toggle:visible').length === 1) | ||||
{ | { | ||||
$('.page-head h1').addClass('list-head').click(function(){ | $('.page-head h1').addClass('list-head').click(function(){ | ||||
@@ -16,22 +16,21 @@ | |||||
<div class="sidebar-items"> | <div class="sidebar-items"> | ||||
<ul class="list-unstyled"> | <ul class="list-unstyled"> | ||||
{% if sidebar_title %} | {% if sidebar_title %} | ||||
<li class="title"> | |||||
{{ sidebar_title }} | |||||
</li> | |||||
{% else %} | |||||
<li class="sidebar-item"> | |||||
<a href="/me">My Account</a> | |||||
<li class="title"> | |||||
{{ sidebar_title }} | |||||
</li> | </li> | ||||
{% endif %} | {% endif %} | ||||
{% for item in sidebar_items -%} | |||||
{% for item in sidebar_items -%} | |||||
<li class="sidebar-item"> | <li class="sidebar-item"> | ||||
<a href="{{ item.route }}" class="text-muted {{ 'active' if pathname==item.route else '' }}" | <a href="{{ item.route }}" class="text-muted {{ 'active' if pathname==item.route else '' }}" | ||||
{% if item.target %}target="{{ item.target }}"{% endif %}> | {% if item.target %}target="{{ item.target }}"{% endif %}> | ||||
{{ _(item.title) }} | {{ _(item.title) }} | ||||
</a> | </a> | ||||
</li> | </li> | ||||
{%- endfor %} | |||||
{%- endfor %} | |||||
<li class="sidebar-item"> | |||||
<a href="/me">My Account</a> | |||||
</li> | |||||
</ul> | </ul> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
@@ -61,7 +61,10 @@ def get_allowed_functions_for_jenv(): | |||||
import mimetypes | import mimetypes | ||||
datautils = {} | datautils = {} | ||||
date_format = frappe.db.get_default("date_format") or "yyyy-mm-dd" | |||||
if frappe.db: | |||||
date_format = frappe.db.get_default("date_format") or "yyyy-mm-dd" | |||||
else: | |||||
date_format = 'yyyy-mm-dd' | |||||
for key, obj in frappe.utils.data.__dict__.items(): | for key, obj in frappe.utils.data.__dict__.items(): | ||||
if key.startswith("_"): | if key.startswith("_"): | ||||
@@ -114,7 +114,6 @@ def add_sidebar_data(context): | |||||
if not context.sidebar_items: | if not context.sidebar_items: | ||||
sidebar_items = frappe.cache().hget('portal_menu_items', frappe.session.user) | sidebar_items = frappe.cache().hget('portal_menu_items', frappe.session.user) | ||||
print sidebar_items | |||||
if sidebar_items == None: | if sidebar_items == None: | ||||
sidebar_items = [] | sidebar_items = [] | ||||
roles = frappe.get_roles() | roles = frappe.get_roles() | ||||
@@ -95,9 +95,9 @@ def get_context(context): | |||||
""") | """) | ||||
def get_context(self, context): | def get_context(self, context): | ||||
from frappe.www.list import get_context as get_list_context | |||||
'''Build context to render the `web_form.html` template''' | |||||
self.set_web_form_module() | |||||
frappe.form_dict.is_web_form = 1 | |||||
logged_in = frappe.session.user != "Guest" | logged_in = frappe.session.user != "Guest" | ||||
doc, delimeter = make_route_string(frappe.form_dict) | doc, delimeter = make_route_string(frappe.form_dict) | ||||
@@ -120,9 +120,7 @@ def get_context(context): | |||||
if self.allow_edit: | if self.allow_edit: | ||||
if self.allow_multiple: | if self.allow_multiple: | ||||
if not frappe.form_dict.name and not frappe.form_dict.new: | if not frappe.form_dict.name and not frappe.form_dict.new: | ||||
frappe.form_dict.doctype = self.doc_type | |||||
get_list_context(context) | |||||
context.is_list = True | |||||
self.build_as_list(context) | |||||
else: | else: | ||||
name = frappe.db.get_value(self.doc_type, {"owner": frappe.session.user}, "name") | name = frappe.db.get_value(self.doc_type, {"owner": frappe.session.user}, "name") | ||||
if name: | if name: | ||||
@@ -135,6 +133,25 @@ def get_context(context): | |||||
if not self.login_required or not self.allow_edit: | if not self.login_required or not self.allow_edit: | ||||
frappe.form_dict.new = 1 | frappe.form_dict.new = 1 | ||||
self.load_document(context) | |||||
context.parents = self.get_parents(context) | |||||
if self.breadcrumbs: | |||||
context.parents = eval(self.breadcrumbs) | |||||
context.has_header = ((frappe.form_dict.name or frappe.form_dict.new) | |||||
and (frappe.session.user!="Guest" or not self.login_required)) | |||||
if context.success_message: | |||||
context.success_message = context.success_message.replace("\n", | |||||
"<br>").replace("'", "\'") | |||||
self.add_custom_context_and_script(context) | |||||
self.add_payment_gateway_url(context) | |||||
context.max_attachment_size = get_max_file_size() | |||||
def load_document(self, context): | |||||
'''Load document `doc` and `layout` properties for template''' | |||||
if frappe.form_dict.name or frappe.form_dict.new: | if frappe.form_dict.name or frappe.form_dict.new: | ||||
context.layout = self.get_layout() | context.layout = self.get_layout() | ||||
context.parents = [{"route": self.route, "title": self.title }] | context.parents = [{"route": self.route, "title": self.title }] | ||||
@@ -147,25 +164,27 @@ def get_context(context): | |||||
context.reference_doctype = context.doc.doctype | context.reference_doctype = context.doc.doctype | ||||
context.reference_name = context.doc.name | context.reference_name = context.doc.name | ||||
if self.allow_comments and frappe.form_dict.name: | |||||
context.comment_list = get_comment_list(context.doc.doctype, | |||||
context.doc.name) | |||||
if self.allow_comments: | |||||
context.comment_list = get_comment_list(context.doc.doctype, | |||||
context.doc.name) | |||||
context.parents = self.get_parents(context) | |||||
def build_as_list(self, context): | |||||
'''Web form is a list, show render as list.html''' | |||||
from frappe.www.list import get_context as get_list_context | |||||
if self.breadcrumbs: | |||||
context.parents = eval(self.breadcrumbs) | |||||
# set some flags to make list.py/list.html happy | |||||
frappe.form_dict.web_form_name = self.name | |||||
frappe.form_dict.doctype = self.doc_type | |||||
frappe.flags.web_form = self | |||||
context.has_header = ((frappe.form_dict.name or frappe.form_dict.new) | |||||
and (frappe.session.user!="Guest" or not self.login_required)) | |||||
self.update_list_context(context) | |||||
get_list_context(context) | |||||
context.is_list = True | |||||
if context.success_message: | |||||
context.success_message = context.success_message.replace("\n", | |||||
"<br>").replace("'", "\'") | |||||
self.add_custom_context_and_script(context) | |||||
self.add_payment_gateway_url(context) | |||||
context.max_attachment_size = get_max_file_size() | |||||
def update_list_context(self, context): | |||||
'''update list context for stanard modules''' | |||||
if self.web_form_module and hasattr(self.web_form_module, 'get_list_context'): | |||||
self.web_form_module.get_list_context(context) | |||||
def add_payment_gateway_url(self, context): | def add_payment_gateway_url(self, context): | ||||
if context.doc and self.accept_payment: | if context.doc and self.accept_payment: | ||||
@@ -191,23 +210,17 @@ def get_context(context): | |||||
def add_custom_context_and_script(self, context): | def add_custom_context_and_script(self, context): | ||||
'''Update context from module if standard and append script''' | '''Update context from module if standard and append script''' | ||||
if self.is_standard: | |||||
module_name = "{app}.{module}.web_form.{name}.{name}".format( | |||||
app = frappe.local.module_app[scrub(self.module)], | |||||
module = scrub(self.module), | |||||
name = scrub(self.name) | |||||
) | |||||
module = frappe.get_module(module_name) | |||||
new_context = module.get_context(context) | |||||
if self.web_form_module: | |||||
new_context = self.web_form_module.get_context(context) | |||||
if new_context: | if new_context: | ||||
context.update(new_context) | context.update(new_context) | ||||
js_path = os.path.join(os.path.dirname(module.__file__), scrub(self.name) + '.js') | |||||
js_path = os.path.join(os.path.dirname(self.web_form_module.__file__), scrub(self.name) + '.js') | |||||
if os.path.exists(js_path): | if os.path.exists(js_path): | ||||
context.script = open(js_path, 'r').read() | context.script = open(js_path, 'r').read() | ||||
css_path = os.path.join(os.path.dirname(module.__file__), scrub(self.name) + '.css') | |||||
css_path = os.path.join(os.path.dirname(self.web_form_module.__file__), scrub(self.name) + '.css') | |||||
if os.path.exists(css_path): | if os.path.exists(css_path): | ||||
context.style = open(css_path, 'r').read() | context.style = open(css_path, 'r').read() | ||||
@@ -267,13 +280,26 @@ def get_context(context): | |||||
def get_parents(self, context): | def get_parents(self, context): | ||||
parents = None | parents = None | ||||
if context.is_list: | |||||
if context.is_list and not context.parents: | |||||
parents = [{"title": _("My Account"), "name": "me"}] | parents = [{"title": _("My Account"), "name": "me"}] | ||||
elif context.parents: | elif context.parents: | ||||
parents = context.parents | parents = context.parents | ||||
return parents | return parents | ||||
def set_web_form_module(self): | |||||
'''Get custom web form module if exists''' | |||||
if self.is_standard: | |||||
module_name = "{app}.{module}.web_form.{name}.{name}".format( | |||||
app = frappe.local.module_app[scrub(self.module)], | |||||
module = scrub(self.module), | |||||
name = scrub(self.name) | |||||
) | |||||
self.web_form_module = frappe.get_module(module_name) | |||||
else: | |||||
self.web_form_module = None | |||||
@frappe.whitelist(allow_guest=True) | @frappe.whitelist(allow_guest=True) | ||||
def accept(web_form, data): | def accept(web_form, data): | ||||
data = frappe._dict(json.loads(data)) | data = frappe._dict(json.loads(data)) | ||||
@@ -388,7 +414,7 @@ def make_route_string(parameters): | |||||
delimeter = '?' | delimeter = '?' | ||||
if isinstance(parameters, dict): | if isinstance(parameters, dict): | ||||
for key in parameters: | for key in parameters: | ||||
if key != "is_web_form": | |||||
if key != "web_form_name": | |||||
route_string += route_string + delimeter + key + "=" + cstr(parameters[key]) | route_string += route_string + delimeter + key + "=" + cstr(parameters[key]) | ||||
delimeter = '&' | delimeter = '&' | ||||
return (route_string, delimeter) | return (route_string, delimeter) |
@@ -73,7 +73,7 @@ def get(doctype, txt=None, limit_start=0, limit=20, **kwargs): | |||||
def set_route(context): | def set_route(context): | ||||
'''Set link for the list item''' | '''Set link for the list item''' | ||||
if context.is_web_form: | |||||
if context.web_form_name: | |||||
context.route = "{0}?name={1}".format(context.pathname, quoted(context.doc.name)) | context.route = "{0}?name={1}".format(context.pathname, quoted(context.doc.name)) | ||||
elif context.doc and getattr(context.doc, 'route', None): | elif context.doc and getattr(context.doc, 'route', None): | ||||
context.route = context.doc.route | context.route = context.doc.route | ||||
@@ -89,7 +89,7 @@ def prepare_filters(doctype, kwargs): | |||||
# resolve additional filters from path | # resolve additional filters from path | ||||
resolve_path(filters.pathname) | resolve_path(filters.pathname) | ||||
for key, val in frappe.local.form_dict.items(): | for key, val in frappe.local.form_dict.items(): | ||||
if key not in filters: | |||||
if key not in filters and key != 'flags': | |||||
filters[key] = val | filters[key] = val | ||||
# filter the filters to include valid fields only | # filter the filters to include valid fields only | ||||
@@ -97,9 +97,6 @@ def prepare_filters(doctype, kwargs): | |||||
if not meta.has_field(fieldname): | if not meta.has_field(fieldname): | ||||
del filters[fieldname] | del filters[fieldname] | ||||
if "is_web_form" in filters: | |||||
del filters["is_web_form"] | |||||
return filters | return filters | ||||
def get_list_context(context, doctype): | def get_list_context(context, doctype): | ||||
@@ -111,12 +108,20 @@ def get_list_context(context, doctype): | |||||
if hasattr(module, "get_list_context"): | if hasattr(module, "get_list_context"): | ||||
list_context = frappe._dict(module.get_list_context(context) or {}) | list_context = frappe._dict(module.get_list_context(context) or {}) | ||||
# is web form | |||||
if cint(frappe.local.form_dict.is_web_form): | |||||
list_context.is_web_form = 1 | |||||
# is web form, show the default web form filters | |||||
# which is only the owner | |||||
if frappe.form_dict.web_form_name: | |||||
list_context.web_form_name = frappe.form_dict.web_form_name | |||||
if not list_context.get("get_list"): | if not list_context.get("get_list"): | ||||
list_context.get_list = get_web_form_list | list_context.get_list = get_web_form_list | ||||
if not frappe.flags.web_form: | |||||
# update list context from web_form | |||||
frappe.flags.web_form = frappe.get_doc('Web Form', frappe.form_dict.web_form_name) | |||||
if frappe.flags.web_form.is_standard: | |||||
frappe.flags.web_form.update_list_context(list_context) | |||||
return list_context | return list_context | ||||
def get_list(doctype, txt, filters, limit_start, limit_page_length=20, ignore_permissions=False, | def get_list(doctype, txt, filters, limit_start, limit_page_length=20, ignore_permissions=False, | ||||