Browse Source

[enhance] web form pagination frappe/shishuvan#3 (#2076)

* [enhance] web form pagination frappe/shishuvan#3

* [minor] add label in web form grid

* [minor] select module for exporting web form

* [fix] more fixes, #2057
version-14
Rushabh Mehta 8 years ago
committed by GitHub
parent
commit
74cb41ae71
10 changed files with 189 additions and 58 deletions
  1. +4
    -1
      frappe/change_log/v7/v7_1_0.md
  2. +13
    -0
      frappe/commands/utils.py
  3. +1
    -0
      frappe/public/css/form.css
  4. +1
    -2
      frappe/public/js/frappe/form/footer/assign_to.js
  5. +5
    -3
      frappe/public/js/frappe/form/templates/grid_body.html
  6. +1
    -0
      frappe/public/less/form.less
  7. +110
    -21
      frappe/templates/generators/web_form.html
  8. +2
    -2
      frappe/website/doctype/web_form/web_form.json
  9. +50
    -27
      frappe/website/doctype/web_form/web_form.py
  10. +2
    -2
      frappe/website/doctype/web_form_field/web_form_field.json

+ 4
- 1
frappe/change_log/v7/v7_1_0.md View File

@@ -1,2 +1,5 @@
- Search for help from within the app. Click on "Help"
- Send a popup to all users on login for a new Note by checking on "Notify users with a popup when they log in"
- Send a popup to all users on login for a new Note by checking on "Notify users with a popup when they log in"
- Updates to Web Form
- Add grids (child tables)
- Add page breaks (for long forms)

+ 13
- 0
frappe/commands/utils.py View File

@@ -200,6 +200,13 @@ def export_fixtures(context):
def import_doc(context, path, force=False):
"Import (insert/update) doclist. If the argument is a directory, all files ending with .json are imported"
from frappe.core.page.data_import_tool import data_import_tool

if not os.path.exists(path):
path = os.path.join('..', path)
if not os.path.exists(path):
print 'Invalid path {0}'.format(path)
sys.exit(1)

for site in context.sites:
try:
frappe.init(site=site)
@@ -222,6 +229,12 @@ def import_csv(context, path, only_insert=False, submit_after_import=False, igno
from frappe.utils.csvutils import read_csv_content
site = get_site(context)

if not os.path.exists(path):
path = os.path.join('..', path)
if not os.path.exists(path):
print 'Invalid path {0}'.format(path)
sys.exit(1)

with open(path, 'r') as csvfile:
content = read_csv_content(csvfile.read())



+ 1
- 0
frappe/public/css/form.css View File

@@ -440,6 +440,7 @@ select.form-control {
}
.form-headline {
padding: 0px 15px;
margin: 0px;
}
.form-headline .alert {
font-size: 12px;


+ 1
- 2
frappe/public/js/frappe/form/footer/assign_to.js View File

@@ -153,10 +153,9 @@ frappe.ui.to_do_dialog = function(opts){
var dialog = new frappe.ui.Dialog({
title: __('Add to To Do'),
fields: [
{fieldtype:'Check', fieldname:'myself', label:__("Assign to me"), "default":0},
{fieldtype: 'Section Break'},
{fieldtype: 'Link', fieldname:'assign_to', options:'User',
label:__("Assign To"), reqd:true, filters: {'user_type': 'System User'}},
{fieldtype:'Check', fieldname:'myself', label:__("Assign to me"), "default":0},
{fieldtype:'Small Text', fieldname:'description', label:__("Comment"), reqd:true},
{fieldtype: 'Section Break'},
{fieldtype: 'Column Break'},


+ 5
- 3
frappe/public/js/frappe/form/templates/grid_body.html View File

@@ -7,11 +7,13 @@
<div class="small form-clickable-section grid-footer">
<div class="row">
<div class="col-sm-6 grid-buttons">
<a href="#" class="grid-add-multiple-rows btn btn-xs btn-default hide"
<button type="reset"
class="grid-add-multiple-rows btn btn-xs btn-default hide"
style="margin-right: 10px;">
{%= __("Add multiple rows") %}</a>
<a href="#" class="btn btn-xs btn-default grid-add-row">
{%= __("Add new row") %}</a>
<!-- hack to allow firefox include this in tabs -->
<button type="reset" class="btn btn-xs btn-default grid-add-row">
{%= __("Add new row") %}</button>
</div>
<div class="col-sm-6 text-right">
<a href="#" class="grid-download btn btn-xs btn-default hide"


+ 1
- 0
frappe/public/less/form.less View File

@@ -555,6 +555,7 @@ select.form-control {

.form-headline {
padding: 0px 15px;
margin: 0px;
}

.form-headline .alert {


+ 110
- 21
frappe/templates/generators/web_form.html View File

@@ -15,7 +15,7 @@
<a href="{{ cancel_url or pathname }}" class="btn btn-default btn-sm">
{{ _("Cancel") }}</a>
<button type="submit" class="btn btn-primary btn-sm btn-form-submit">
{{ _("Submit") if frappe.form_dict.new else _("Update") }}</button>
{{ _("Submit") if frappe.form_dict.new else _("Save") }}</button>
{% elif is_list %}
<div style="padding-bottom: 15px;">
<a href="/{{ pathname }}{{ delimeter }}new=1" class="btn btn-primary btn-new btn-sm">
@@ -93,6 +93,18 @@
value="{{ value(field, _doc) }}">
{{ help(field) }}
</div>
{% elif field.fieldtype=="Link" %}
<div class="form-group">
{% if with_label %}{{ label(field) }}{% endif %}
<select class="form-control" {{ properties(field) }}>
{% for option in ([{"name":""}] + frappe.get_all(field.options)) -%}
<option value="{{ option.name }}"
{{ 'selected="selected"' if value(field, _doc)==option.name else '' }}>
{{ option.name }}</option>
{%- endfor %}
</select>
{{ help(field) }}
</div>
{% elif field.fieldtype=="Select" %}
<div class="form-group">
{% if with_label %}{{ label(field) }}{% endif %}
@@ -136,8 +148,8 @@
{% if with_label %}
<label>
<input type="checkbox" id="{{ field.fieldname }}"
name="{{ field.fieldname }}"
{{ doc and doc.get(field.fieldname) and 'checked' or '' }}>
name="{{ field.fieldname }}" data-doctype="{{ field.parent }}"
{{ _doc and _doc.get(field.fieldname) and 'checked' or '' }}>
{{ _(field.label) }}
</label>
{% endif %}
@@ -152,7 +164,7 @@
{% if d != None %}data-name="{{ d.name }}" data-child-row=1{% endif %}>
{% for df in frappe.get_meta(field.options).fields %}
{% if df.in_list_view %}
<{{ 'th' if d==None else 'td' }} style="width: {{ (field.columns or 2) * 8.3333 }}%;">
<{{ 'th' if d==None else 'td' }} style="width: {{ (df.columns or 2) * 8.3333 }}%;">
{% if d!=None %}
{{ render_field(df, d, False) }}
{% else %}
@@ -170,6 +182,7 @@
{% endmacro %}

{% macro render_table(field) %}
{{ label(field) }}
<div class='web-form-grid'
data-fieldname='{{ field.fieldname }}' data-doctype='{{ field.options }}'>
<table class='table table-bordered'>
@@ -192,6 +205,15 @@
data-fieldname='{{ field.fieldname }}'>{{ _("Add Row") }}</button></p>
{% endmacro %}

{% if layout|len > 1 %}
<div class="text-center slide-progress text-extra-muted">
{% for page in layout %}
<i data-idx="{{ loop.index }}" class="icon-fixed-width
{% if loop.index==1 %}icon-circle{% else %}icon-circle-blank{% endif %}"></i>
{% endfor %}
</div>
{% endif %}

<div class="form-message text-muted hide"></div>
<form role="form"
data-web-form="{{ name }}" data-owner="{{ doc.owner }}">
@@ -210,24 +232,50 @@
data-doctype="{{ doc_type }}">
{%- endif %}

{% for section in layout %}
{% if section.label %}
<h5 class='uppercase'>{{ _(section.label) }}</h5>
{% endif %}
<div class="row">
{% for column in section.columns %}
<div class="col-sm-{{ (12 / (section.columns|len))|int }}">
{% for field in column %}
{% if field.fieldtype=='Table' %}
{{ render_table(field) }}
{% else %}
{{ render_field(field, doc) }}
{% endif %}
{% endfor %}
</div>
{% endfor %}
{% for page in layout %}
<div class="web-form-page{% if loop.index > 1 %} hidden{% endif %}"
data-idx="{{ loop.index }}">
<h2>{{ page.label }}</h2>
{% for section in page.sections %}
<div class="section">
{% if section.label %}
<h5 class='uppercase'>{{ _(section.label) }}</h5>
{% endif %}
<div class="row">
{% for column in section.columns %}
<div class="col-sm-{{ (12 / (section.columns|len))|int }}">
{% for field in column %}
{% if field.fieldtype=='Table' %}
{{ render_table(field) }}
{% else %}
{{ render_field(field, doc) }}
{% endif %}
{% endfor %}
</div>
{% endfor %}
</div>
</div>
{% endfor %}
<!-- page footer buttons -->
<div class='text-right'>
<br>
{% if loop.index > 1 %}
<button class='btn btn-sm btn-default btn-change-section'
data-idx="{{ loop.index - 1 }}">
{{ _("Previous") }}</button>
{% endif %}
{% if loop.index == layout|len %}
<button type="submit" class="btn btn-primary btn-sm btn-form-submit">
{{ _("Submit") if frappe.form_dict.new else _("Update") }}</button>
{% elif layout|len > 1 %}
<button class="btn btn-primary btn-sm btn-change-section"
data-idx="{{ loop.index + 1 }}">
{{ _("Next") }}</button>
{% endif %}
</div>
</div>
{% endfor %}

</form>
{% if allow_comments and not frappe.form_dict.new -%}
<div class="comments">
@@ -283,6 +331,29 @@ frappe.ready(function() {
return false;
});

// change section
$('.btn-change-section, .slide-progress .icon-fixed-width').on('click', function() {
var idx = $(this).attr('data-idx');
show_slide(idx);
});

show_slide = function(idx) {
// hide all sections
$('.web-form-page').addClass('hidden');

// slide-progress
$('.slide-progress .icon-fixed-width.icon-circle')
.removeClass('icon-circle').addClass('icon-circle-blank');
$('.slide-progress .icon-fixed-width[data-idx="'+idx+'"]')
.removeClass('icon-circle-blank').addClass('icon-circle');

// un hide target section
$('.web-form-page[data-idx="'+idx+'"]')
.removeClass('hidden')
.find(':input:first').focus();

}

// add row
$('.btn-add-row').on('click', function() {
var fieldname = $(this).attr('data-fieldname');
@@ -343,7 +414,7 @@ frappe.ready(function() {
if(input_type==="file") {
var val = $input.get(0).filedata;
} else if(input_type==="checkbox") {
var val = $input.is(":checked") ? 1 : 0;
var val = $input.prop("checked") ? 1 : 0;
} else if($input.attr("data-fieldtype")==="Date") {
var val = $.datepicker.formatDate("yy-mm-dd",
$input.datepicker('getDate'));
@@ -496,6 +567,24 @@ input, select {
.web-form-grid-row .form-group {
margin: 0px;
}

.slide-progress {
/*border-top: 1px solid #d1d8dd;*/
margin-top: -7px;
padding: 15px 0px;
}
.slide-progress .icon-fixed-width {
vertical-align: middle;
margin-right: 7px;
cursor: pointer;
}
.slide-progress .icon-circle-blank {
font-size: 12px;
}
.slide-progress .icon-circle {
font-size: 14px;
}

{% if style is defined %}{{ style }}{% endif %}
</style>
{% endblock %}

+ 2
- 2
frappe/website/doctype/web_form/web_form.json View File

@@ -95,7 +95,7 @@
"columns": 0,
"fieldname": "module",
"fieldtype": "Link",
"hidden": 1,
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
@@ -618,7 +618,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2016-09-13 13:08:13.720070",
"modified": "2016-09-20 07:06:10.839930",
"modified_by": "Administrator",
"module": "Website",
"name": "Web Form",


+ 50
- 27
frappe/website/doctype/web_form/web_form.py View File

@@ -26,27 +26,17 @@ class WebForm(WebsiteGenerator):
def validate(self):
super(WebForm, self).validate()

self.module = frappe.db.get_value('DocType', self.doc_type, 'module')
if not self.module:
self.module = frappe.db.get_value('DocType', self.doc_type, 'module')

if (not (frappe.flags.in_install or frappe.flags.in_patch or frappe.flags.in_test or frappe.flags.in_fixtures)
and self.is_standard and not frappe.conf.developer_mode):
frappe.throw(_("You need to be in developer mode to edit a Standard Web Form"))

def reset_field_parent_and_convert_links_to_selects(self):
def reset_field_parent(self):
'''Convert link fields to select with names as options'''
for df in self.web_form_fields:
df.parent = self.doc_type
if df.fieldtype == "Link":
options = [d.name for d in frappe.get_all(df.options)]
df.fieldtype = "Select"

if len(options)==1:
df.options = options[0]
df.default = options[0]
df.hidden = 1

else:
df.options = "\n".join([""] + options)

def use_meta_fields(self):
'''Override default properties for standard web forms'''
@@ -78,7 +68,7 @@ class WebForm(WebsiteGenerator):
from frappe.modules import get_module_path

# json
export_to_files(record_list=[['Web Form', self.name]])
export_to_files(record_list=[['Web Form', self.name]], record_module=self.module)

# write files
path = os.path.join(get_module_path(self.module), 'web_form', scrub(self.name), scrub(self.name))
@@ -120,7 +110,7 @@ def get_context(context):
if frappe.form_dict.name and not has_web_form_permission(self.doc_type, frappe.form_dict.name):
frappe.throw(_("You don't have the permissions to access this document"), frappe.PermissionError)

self.reset_field_parent_and_convert_links_to_selects()
self.reset_field_parent()

if self.is_standard:
self.use_meta_fields()
@@ -167,7 +157,7 @@ def get_context(context):
"<br>").replace("'", "\'")

self.add_custom_context_and_script(context)
def add_custom_context_and_script(self, context):
'''Update context from module if standard and append script'''
if self.is_standard:
@@ -193,21 +183,54 @@ def get_context(context):

def get_layout(self):
layout = []
for df in self.web_form_fields:
if not layout:
layout.append({'columns': []})
def add_page(df=None):
new_page = {'sections': []}
layout.append(new_page)
if df and df.fieldtype=='Page Break':
new_page['label'] = df.label

if df.fieldtype=="Section Break":
layout.append({'label': df.label, 'columns': [] })
return new_page

if not layout[-1]['columns']:
layout[-1]['columns'].append([])
def add_section(df=None):
new_section = {'columns': []}
layout[-1]['sections'].append(new_section)
if df and df.fieldtype=='Section Break':
new_section['label'] = df.label

if df.fieldtype=="Column Break" or not layout[-1]['columns']:
layout[-1]['columns'].append([])
return new_section

def add_column(df=None):
new_col = []
layout[-1]['sections'][-1]['columns'].append(new_col)

return new_col

page, section, column = None, None, None
for df in self.web_form_fields:

if df.fieldtype not in ("Section Break", "Column Break"):
layout[-1]['columns'][-1].append(df)
# breaks
if df.fieldtype=='Page Break':
page = add_page(df)
section, column = None, None

if df.fieldtype=='Section Break':
section = add_section(df)
column = None

if df.fieldtype=='Column Break':
column = add_column(df)

# input
if df.fieldtype not in ('Section Break', 'Column Break', 'Page Break'):
if not page:
page = add_page()
section, column = None, None
if not section:
section = add_section()
column = None
if not column:
column = add_column()
column.append(df)

return layout



+ 2
- 2
frappe/website/doctype/web_form_field/web_form_field.json View File

@@ -25,7 +25,7 @@
"label": "Fieldtype",
"length": 0,
"no_copy": 0,
"options": "Attach\nCheck\nData\nDate\nDatetime\nHTML\nLink\nSelect\nText\nTable\nSection Break\nColumn Break",
"options": "Attach\nCheck\nData\nDate\nDatetime\nHTML\nLink\nSelect\nText\nTable\nSection Break\nColumn Break\nPage Break",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
@@ -319,7 +319,7 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2016-09-13 12:39:31.889290",
"modified": "2016-09-19 08:02:36.033335",
"modified_by": "Administrator",
"module": "Website",
"name": "Web Form Field",


Loading…
Cancel
Save