Sfoglia il codice sorgente

[wip] grid in web form (#2044)

* [wip] grid in web form

* [complete] webform in grid

* [minor] configurable sidebar items in web form

* [fix] tests

* [style]
version-14
Rushabh Mehta 8 anni fa
committed by GitHub
parent
commit
37eb4eaffc
14 ha cambiato i file con 447 aggiunte e 151 eliminazioni
  1. +11
    -2
      frappe/email/doctype/newsletter/newsletter.json
  2. +3
    -0
      frappe/email/doctype/newsletter/newsletter.py
  3. +7
    -0
      frappe/public/css/common.css
  4. +7
    -0
      frappe/public/css/desk.css
  5. +7
    -0
      frappe/public/css/website.css
  6. +9
    -0
      frappe/public/less/common.less
  7. +214
    -72
      frappe/templates/generators/web_form.html
  8. +8
    -7
      frappe/website/context.py
  9. +8
    -2
      frappe/website/doctype/portal_menu_item/portal_menu_item.json
  10. +17
    -16
      frappe/website/doctype/web_form/test_web_form.py
  11. +26
    -14
      frappe/website/doctype/web_form/web_form.js
  12. +76
    -1
      frappe/website/doctype/web_form/web_form.json
  13. +36
    -31
      frappe/website/doctype/web_form/web_form.py
  14. +18
    -6
      frappe/website/doctype/web_form_field/web_form_field.json

+ 11
- 2
frappe/email/doctype/newsletter/newsletter.json Vedi File

@@ -2,7 +2,7 @@
"allow_copy": 0,
"allow_import": 0,
"allow_rename": 1,
"autoname": "field:subject",
"autoname": "",
"beta": 0,
"creation": "2013-01-10 16:34:31",
"custom": 0,
@@ -16,6 +16,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "email_group",
"fieldtype": "Link",
"hidden": 0,
@@ -42,6 +43,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "subject",
"fieldtype": "Small Text",
"hidden": 0,
@@ -66,6 +68,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"description": "",
"fieldname": "send_from",
"fieldtype": "Data",
@@ -91,6 +94,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "email_sent",
"fieldtype": "Check",
"hidden": 0,
@@ -115,6 +119,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "newsletter_content",
"fieldtype": "Section Break",
"hidden": 0,
@@ -139,6 +144,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "message",
"fieldtype": "Text Editor",
"hidden": 0,
@@ -163,6 +169,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"description": "",
"fieldname": "test_the_newsletter",
"fieldtype": "Section Break",
@@ -188,6 +195,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"description": "A Lead with this email id should exist",
"fieldname": "test_email_id",
"fieldtype": "Data",
@@ -213,6 +221,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "test_send",
"fieldtype": "Button",
"hidden": 0,
@@ -247,7 +256,7 @@
"istable": 0,
"max_attachments": 0,
"menu_index": 0,
"modified": "2016-08-05 06:26:58.705579",
"modified": "2016-09-13 11:33:47.892910",
"modified_by": "Administrator",
"module": "Email",
"name": "Newsletter",


+ 3
- 0
frappe/email/doctype/newsletter/newsletter.py Vedi File

@@ -15,6 +15,9 @@ from frappe.email.queue import send
from frappe.email.doctype.email_group.email_group import add_subscribers

class Newsletter(Document):
def autoname(self):
self.name = self.subject

def onload(self):
if self.email_sent:
self.get("__onload").status_count = dict(frappe.db.sql("""select status, count(name)


+ 7
- 0
frappe/public/css/common.css Vedi File

@@ -228,3 +228,10 @@ a.no-decoration:active {
-webkit-filter: grayscale(100%);
filter: grayscale(100%);
}
.uppercase {
padding-bottom: 4px;
text-transform: uppercase;
font-size: 12px;
letter-spacing: 0.4px;
color: #8D99A6;
}

+ 7
- 0
frappe/public/css/desk.css Vedi File

@@ -228,6 +228,13 @@ a.no-decoration:active {
-webkit-filter: grayscale(100%);
filter: grayscale(100%);
}
.uppercase {
padding-bottom: 4px;
text-transform: uppercase;
font-size: 12px;
letter-spacing: 0.4px;
color: #8D99A6;
}
.nav-pills a,
.nav-pills a:hover {
border-bottom: none;


+ 7
- 0
frappe/public/css/website.css Vedi File

@@ -228,6 +228,13 @@ a.no-decoration:active {
-webkit-filter: grayscale(100%);
filter: grayscale(100%);
}
.uppercase {
padding-bottom: 4px;
text-transform: uppercase;
font-size: 12px;
letter-spacing: 0.4px;
color: #8D99A6;
}
.avatar {
display: inline-block;
vertical-align: middle;


+ 9
- 0
frappe/public/less/common.less Vedi File

@@ -263,3 +263,12 @@ a.no-decoration& {
-webkit-filter: grayscale(100%);
filter: grayscale(100%);
}

.uppercase {
padding-bottom: 4px;
text-transform: uppercase;
font-size: 12px;
letter-spacing: 0.4px;
color: @text-muted;
}


+ 214
- 72
frappe/templates/generators/web_form.html Vedi File

@@ -18,7 +18,7 @@
{{ _("Submit") if frappe.form_dict.new else _("Update") }}</button>
{% elif is_list %}
<div style="padding-bottom: 15px;">
<a href="/{{ pathname + args }}{{ delimeter }}new=1" class="btn btn-primary btn-new btn-sm">
<a href="/{{ pathname }}{{ delimeter }}new=1" class="btn btn-primary btn-new btn-sm">
{{ _("New {0}").format(_(doc_type)) }}
</a>
</div>
@@ -50,17 +50,22 @@
<br>

{%- macro properties(field) %}
name="{{ field.fieldname }}" id="{{ field.fieldname }}"
name="{{ field.fieldname }}"
{% if field.placeholder -%} placeholder="{{ _(field.placeholder) }}" {%- endif %}
data-label="{{ _(field.label) }}" data-fieldtype="{{ field.fieldtype }}"
data-doctype="{{ field.parent }}" data-default="{{ field.default or "" }}"
{{ (field.reqd and field.fieldtype!="Attach") and "required" or "" }}
{{ field.read_only and "disabled" or "" }}
{% endmacro -%}

{%- macro value(field) -%}{% if doc %}{{
doc.get(field.fieldname) or
field.default or
frappe.form_dict.get(field.fieldname) or "" }}{% else %}{{ getCookie(field.options) or field.default or "" }}{% endif %}{%- endmacro -%}
{%- macro value(field, _doc) -%}
{%- if _doc -%}
{{ _doc.get(field.fieldname) or field.default
or frappe.form_dict.get(field.fieldname) or "" }}
{%- else -%}
{{ field.default or "" }}
{%- endif -%}
{%- endmacro -%}

{%- macro help(field) -%}
{% if field.description -%}
@@ -73,7 +78,7 @@
{{ _(field.label) }}</label>
{% endmacro %}

{% macro render_field(field) %}
{% macro render_field(field, _doc=None, with_label=True) %}
{% if field.hidden %}
<input type="hidden"
name="{{ field.fieldname }}" {% if field.default -%} value="{{ field.default }}" {%- endif %}>
@@ -83,18 +88,18 @@
</div>
{% elif field.fieldtype in ("Data", "Date", "Datetime") %}
<div class="form-group">
{{ label(field) }}
{% if with_label %}{{ label(field) }}{% endif %}
<input type="text" class="form-control" {{ properties(field) }}
value="{{ value(field) }}">
value="{{ value(field, _doc) }}">
{{ help(field) }}
</div>
{% elif field.fieldtype=="Select" %}
<div class="form-group">
{{ label(field) }}
{% if with_label %}{{ label(field) }}{% endif %}
<select class="form-control" {{ properties(field) }}>
{% for option in field.options.split("\n") -%}
<option value="{{ option }}"
{{ 'selected="selected"' if value(field)==option else '' }}>
{{ 'selected="selected"' if value(field, _doc)==option else '' }}>
{{ option }}</option>
{%- endfor %}
</select>
@@ -102,24 +107,24 @@
</div>
{% elif field.fieldtype=="Text" %}
<div class="form-group">
{{ label(field) }}
{% if with_label %}{{ label(field) }}{% endif %}
{{ help(field) }}
<textarea class="form-control" style="height: 200px;"
{{ properties(field) }}>{{ value(field) }}</textarea>
{{ properties(field) }}>{{ value(field, _doc) }}</textarea>
</div>
{% elif field.fieldtype=="Attach" %}
<div class="form-group">
{{ label(field) }}
{% if value(field) -%}
{% if with_label %}{{ label(field) }}{% endif %}
{% if value(field, _doc) -%}
<p class="small">
<a href="{{ doc.get(field.fieldname) }}" target="blank">
{{ doc.get(field.fieldname) }}
{{ _doc.get(field.fieldname) }}
</a>
<br><button class="btn btn-small btn-default btn-xs
change-attach" style="margin-top: 5px;">Change</button>
</p>
{%- endif %}
<p class="{{ value(field) and 'hide' or '' }} attach-input-wrap">
<p class="{{ value(field, _doc) and 'hide' or '' }} attach-input-wrap">
<input type="file" style="margin-top: 7px;"
{{ properties(field) }}>
</p>
@@ -128,18 +133,65 @@
{% elif field.fieldtype=="Check" %}
<div class="form-group">
<div class="checkbox">
{% if with_label %}
<label>
<input type="checkbox" id="{{ field.fieldname }}"
name="{{ field.fieldname }}"
{{ doc and doc.get(field.fieldname) and 'checked' or '' }}>
{{ _(field.label) }}
</label>
{% endif %}
{{ help(field) }}
</div>
</div>
{% endif %}
{% endmacro %}

{% macro render_row(field, d=None, hidden=False) %}
<tr class="web-form-grid-row {% if hidden %}hidden{% endif %}"
{% 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 }}%;">
{% if d!=None %}
{{ render_field(df, d, False) }}
{% else %}
<span class='text-muted small'>{{ df.label }}</span>
{% endif %}
</{{ 'th' if d.name==None else 'td' }}>
{% endif %}
{% endfor %}
<td style="width: 8.3333%">
{% if d!=None %}
<button class='btn btn-default btn-sm btn-remove'><i class='icon-remove'></i></button>
{% endif %}
</td>
</tr>
{% endmacro %}

{% macro render_table(field) %}
<div class='web-form-grid'
data-fieldname='{{ field.fieldname }}' data-doctype='{{ field.options }}'>
<table class='table table-bordered'>
<thead>
{{ render_row(field) }}
</thead>
<tbody>
{{ render_row(field, {}, True) }}
{% if doc.get(field.fieldname) %}
{% for d in doc.get(field.fieldname) %}
{{ render_row(field, d) }}
{% endfor %}
{% else %}
{{ render_row(field, {}) }}
{% endif %}
</tbody>
</table>
</div>
<p><button class='btn btn-default btn-sm btn-add-row'
data-fieldname='{{ field.fieldname }}'>{{ _("Add Row") }}</button></p>
{% endmacro %}

<div class="form-message text-muted hide"></div>
<form role="form"
data-web-form="{{ name }}" data-owner="{{ doc.owner }}">
@@ -153,23 +205,29 @@
</div>
</div>
{% endif %}
<input type="hidden" name="web_form" value="{{ name }}">
<input type="hidden" name="doctype" value="{{ doc_type }}">
{% if frappe.form_dict.name -%}
<input type="hidden" name="name" value="{{ frappe.form_dict.name }}">
<input type="hidden" name="name" value="{{ frappe.form_dict.name }}"
data-doctype="{{ doc_type }}">
{%- endif %}

{% for section in layout %}
{% for section in layout %}
{% if section.label %}
<h5 class='uppercase'>{{ _(section.label) }}</h5>
{% endif %}
<div class="row">
{% for column in section %}
<div class="col-sm-{{ (12 / (section|len))|int }}" style="max-width: 500px;">
{% for column in section.columns %}
<div class="col-sm-{{ (12 / (section.columns|len))|int }}">
{% for field in column %}
{{ render_field(field) }}
{% if field.fieldtype=='Table' %}
{{ render_table(field) }}
{% else %}
{{ render_field(field, doc) }}
{% endif %}
{% endfor %}
</div>
{% endfor %}
</div>
{% endfor %}
{% endfor %}
</form>
{% if allow_comments and not frappe.form_dict.new -%}
<div class="comments">
@@ -186,8 +244,10 @@
<script>
frappe.ready(function() {
window.file_reading = false;
window.success_message = "{{ success_message or "" }}";
window.success_message = "{{ success_message or "" }}";
frappe.datepicker_format = "{{ frappe.date_format.replace('yyyy', 'yy') }}";
var web_form_doctype = "{{ doc_type }}";
var web_form_name = "{{ name }}";
var $form = $("form[data-web-form='{{ name }}']");

// read file attachment
@@ -223,20 +283,61 @@ frappe.ready(function() {
return false;
});

// submit
$(".btn-form-submit").on("click", function() {
var args = {};
if(window.saving)
return;
window.saving = true;
// add row
$('.btn-add-row').on('click', function() {
var fieldname = $(this).attr('data-fieldname');
var grid = $('.web-form-grid[data-fieldname="'+fieldname+'"]');
var new_row = grid.find('.web-form-grid-row.hidden').clone()
.appendTo(grid.find('tbody'))
.attr('data-name', '')
.removeClass('hidden');
new_row.find('input').each(function() {
$(this)
.val($(this).attr('data-default') || "")
.removeClass('hasDatepicker')
.attr('id', '');
});
setup_date_picker(new_row);
return false;
});

if(window.file_reading) {
window.saving = false;
frappe.msgprint("Reading file, please retry.");
return;
}
// remove row
$('.web-form-grid').on('click', '.btn-remove', function() {
$(this).parents('.web-form-grid-row:first').remove();
return false;
});

// get document data
var get_data = function() {
var doc = get_data_for_doctype($form, web_form_doctype);
doc.doctype = web_form_doctype;

// get data from child tables
$('.web-form-grid').each(function() {
var fieldname = $(this).attr('data-fieldname');
var doctype = $(this).attr('data-doctype');
doc[fieldname] = [];

$form.find("[name]").each(function() {
// get data from each row
$(this).find('[data-child-row=1]:visible').each(function() {
var d = get_data_for_doctype($(this), doctype);

// set name of child record (if set)
var name = $(this).attr('data-name');
if(name) { d.name = name; }

doc[fieldname].push(d);
});
});

return doc;
}

// get data from input elements
// for the given doctype
var get_data_for_doctype = function(parent, doctype) {
var out = {};
parent.find("[name][data-doctype='"+ doctype +"']").each(function() {
var $input = $(this);
var input_type = $input.attr("type");
if(input_type==="file") {
@@ -257,13 +358,30 @@ frappe.ready(function() {
throw "mandatory missing";
}

args[$input.attr("name")] = val;
out[$input.attr("name")] = val;
});
return out;
}

// submit
$(".btn-form-submit").on("click", function() {
if(window.saving)
return;
window.saving = true;

if(window.file_reading) {
window.saving = false;
frappe.msgprint("Reading file, please retry.");
return;
}

frappe.call({
type: "POST",
method: "frappe.website.doctype.web_form.web_form.accept",
args: args,
args: {
data: get_data(),
web_form: web_form_name
},
freeze: true,
btn: $form.find("[type='submit']"),
callback: function(data) {
@@ -278,7 +396,7 @@ frappe.ready(function() {
} else {
frappe.msgprint(__('Successfully Updated'));
setTimeout(function() {
window.location.href = "{{ success_url }}";
//window.location.href = "{{ success_url }}";
}, 3000);
}
}
@@ -311,40 +429,49 @@ frappe.ready(function() {
}
})

// import date picker / timepicker if required
{% if "Date" in types %}
frappe.require("assets/frappe/js/lib/jquery/jquery-ui.min.js");
frappe.require("assets/frappe/js/lib/jquery/bootstrap_theme/jquery-ui.selected.css");
$form.find("[data-fieldtype='Date']").datepicker({
altFormat:'yy-mm-dd',
changeYear: true,
yearRange: "-70Y:+10Y",
dateFormat: frappe.datepicker_format,
});
// setup datepicker in all inputs within the given element
var setup_date_picker = function(ele) {
var $dates = ele.find("[data-fieldtype='Date']");
var $date_times = ele.find("[data-fieldtype='Datetime']");

// setup date
if($dates.length) {
frappe.require("assets/frappe/js/lib/jquery/jquery-ui.min.js");
frappe.require("assets/frappe/js/lib/jquery/bootstrap_theme/jquery-ui.selected.css");
$dates.datepicker({
altFormat:'yy-mm-dd',
changeYear: true,
yearRange: "-70Y:+10Y",
dateFormat: frappe.datepicker_format,
});

// convert dates to user format
$form.find("[data-fieldtype='Date']").each(function() {
var val = $(this).val();
if(val) {
$(this).val($.datepicker.formatDate(frappe.datepicker_format,
$.datepicker.parseDate("yy-mm-dd", val)));
// convert dates to user format
$dates.each(function() {
var val = $(this).val();
if(val) {
$(this).val($.datepicker.formatDate(frappe.datepicker_format,
$.datepicker.parseDate("yy-mm-dd", val)));
}
});
}
})

{% endif %}
// setup datetime
if($date_times.length) {
frappe.require("assets/frappe/js/lib/jquery/jquery.ui.slider.min.js");
frappe.require("assets/frappe/js/lib/jquery/jquery.ui.sliderAccess.js");
frappe.require("assets/frappe/js/lib/jquery/jquery.ui.timepicker-addon.css");
frappe.require("assets/frappe/js/lib/jquery/jquery.ui.timepicker-addon.js");

$date_times.datetimepicker({
altFormat:'yy-mm-dd',
changeYear: true,
yearRange: "-70Y:+10Y",
dateFormat: frappe.datepicker_format,
});
}
}

{% if "Datetime" in types %}
frappe.require("assets/frappe/js/lib/jquery/jquery.ui.slider.min.js");
frappe.require("assets/frappe/js/lib/jquery/jquery.ui.sliderAccess.js");
frappe.require("assets/frappe/js/lib/jquery/jquery.ui.timepicker-addon.css");
frappe.require("assets/frappe/js/lib/jquery/jquery.ui.timepicker-addon.js");
$form.find("[data-fieldtype='Datetime']").datetimepicker({
altFormat:'yy-mm-dd',
changeYear: true,
yearRange: "-70Y:+10Y",
dateFormat: frappe.datepicker_format,
})
{% endif %}
setup_date_picker($form);
});

{% if script is defined %}
@@ -355,5 +482,20 @@ frappe.ready(function() {
{% endblock %}

{% block style %}
{% if style is defined %}<style>{{ style }}</style>{% endif %}
<style>
input, select {
max-width: 500px;
}
.web-form-grid-row input, .web-form-grid-row select {
border: 0px;
padding: 0px;
}
.web-form-grid-row input:focus, .web-form-grid-row select:focus {
box-shadow: none;
}
.web-form-grid-row .form-group {
margin: 0px;
}
{% if style is defined %}{{ style }}{% endif %}
</style>
{% endblock %}

+ 8
- 7
frappe/website/context.py Vedi File

@@ -95,14 +95,15 @@ def add_sidebar_data(context):
from frappe.utils.user import get_fullname_and_avatar
import frappe.www.list

sidebar_items = json.loads(frappe.cache().get('sidebar_items') or '[]')
if not sidebar_items:
sidebar_items = frappe.get_all('Portal Menu Item',
fields=['title', 'route', 'reference_doctype', 'show_always'],
filters={'enabled': 1}, order_by='idx asc')
frappe.cache().set('portal_menu_items', json.dumps(sidebar_items))

if not context.sidebar_items:
sidebar_items = json.loads(frappe.cache().get_value('portal_menu_items') or '[]')

if not sidebar_items:
sidebar_items = frappe.get_all('Portal Menu Item',
fields=['title', 'route', 'reference_doctype', 'show_always'],
filters={'enabled': 1, 'parent': 'Portal Settings'}, order_by='idx asc')
frappe.cache().set_value('portal_menu_items', json.dumps(sidebar_items))

context.sidebar_items = sidebar_items

info = get_fullname_and_avatar(frappe.session.user)


+ 8
- 2
frappe/website/doctype/portal_menu_item/portal_menu_item.json Vedi File

@@ -14,6 +14,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "title",
"fieldtype": "Data",
"hidden": 0,
@@ -39,6 +40,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "enabled",
"fieldtype": "Check",
"hidden": 0,
@@ -64,6 +66,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "route",
"fieldtype": "Data",
"hidden": 0,
@@ -78,7 +81,7 @@
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"read_only": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
@@ -89,6 +92,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"description": "",
"fieldname": "reference_doctype",
"fieldtype": "Link",
@@ -116,6 +120,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "target",
"fieldtype": "Data",
"hidden": 0,
@@ -141,6 +146,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "show_always",
"fieldtype": "Check",
"hidden": 0,
@@ -173,7 +179,7 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2016-07-11 03:28:03.883801",
"modified": "2016-09-13 13:08:58.890253",
"modified_by": "Administrator",
"module": "Website",
"name": "Portal Menu Item",


+ 17
- 16
frappe/website/doctype/web_form/test_web_form.py Vedi File

@@ -3,7 +3,7 @@
from __future__ import unicode_literals

import frappe
import unittest
import unittest, json

from frappe.website.render import build_page
from frappe.website.doctype.web_form.web_form import accept
@@ -38,12 +38,12 @@ class TestWebForm(unittest.TestCase):

def test_accept(self):
frappe.set_user("Administrator")
frappe.form_dict.web_form = "manage-events"
frappe.form_dict.doctype = "Event"
frappe.form_dict.subject = "_Test Event Web Form"
frappe.form_dict.description = "_Test Event Description"
frappe.form_dict.starts_on = "2014-09-09"
accept()
accept(web_form='manage-events', data=json.dumps({
'doctype': 'Event',
'subject': '_Test Event Web Form',
'description': '_Test Event Description',
'starts_on': '2014-09-09'
}))

self.event_name = frappe.db.get_value("Event",
{"subject": "_Test Event Web Form"})
@@ -51,17 +51,18 @@ class TestWebForm(unittest.TestCase):

def test_edit(self):
self.test_accept()
frappe.form_dict.web_form = "manage-events"
frappe.form_dict.doctype = "Event"
frappe.form_dict.name = self.event_name
frappe.form_dict.subject = "_Test Event Web Form"
frappe.form_dict.description = "_Test Event Description 1"
frappe.form_dict.starts_on = "2014-09-09"
doc={
'doctype': 'Event',
'subject': '_Test Event Web Form',
'description': '_Test Event Description 1',
'starts_on': '2014-09-09',
'name': self.event_name
}

self.assertNotEquals(frappe.db.get_value("Event",
self.event_name, "description"), frappe.form_dict.description)
self.event_name, "description"), doc.get('description'))

accept()
accept(web_form='manage-events', data=json.dumps(doc))

self.assertEquals(frappe.db.get_value("Event",
self.event_name, "description"), frappe.form_dict.description)
self.event_name, "description"), doc.get('description'))

+ 26
- 14
frappe/website/doctype/web_form/web_form.js Vedi File

@@ -5,8 +5,12 @@ frappe.web_form = {
if(doc.doc_type) {
frappe.model.with_doctype(doc.doc_type, function() {
var fields = $.map(frappe.get_doc("DocType", frm.doc.doc_type).fields, function(d) {
return frappe.model.no_value_type.indexOf(d.fieldtype)===-1 ?
d.fieldname : null;
if(frappe.model.no_value_type.indexOf(d.fieldtype)===-1
|| d.fieldtype==='Table') {
return {label: d.label + ' ('+d.fieldtype+')', value:d.fieldname}
} else {
return null;
}
})
frappe.meta.get_docfield("Web Form Field", "fieldname", frm.doc.name).options
= [""].concat(fields);
@@ -40,18 +44,26 @@ frappe.ui.form.on("Web Form", {
});


frappe.ui.form.on("Web Form Field", "fieldname", function(frm, doctype, name) {
var doc = frappe.get_doc(doctype, name);
var df = $.map(frappe.get_doc("DocType", frm.doc.doc_type).fields, function(d) {
return doc.fieldname==d.fieldname ? d : null; })[0];
frappe.ui.form.on("Web Form Field", {
fieldtype: function(frm, doctype, name) {
var doc = frappe.get_doc(doctype, name);
if(fieldtype==='Section Break' || fieldtype==='Section Break') {
doc.fieldname = '';
frm.refresh_field("web_form_fields");
}
},
fieldname: function(frm, doctype, name) {
var doc = frappe.get_doc(doctype, name);
var df = $.map(frappe.get_doc("DocType", frm.doc.doc_type).fields, function(d) {
return doc.fieldname==d.fieldname ? d : null; })[0];

doc.label = df.label;
doc.reqd = df.reqd;
doc.options = df.options;
doc.fieldtype = frappe.meta.get_docfield("Web Form Field", "fieldtype")
.options.split("\n").indexOf(df.fieldtype)===-1 ? "Data" : df.fieldtype;
doc.description = df.description;
doc["default"] = df["default"];
doc.label = df.label;
doc.reqd = df.reqd;
doc.options = df.options;
doc.fieldtype = frappe.meta.get_docfield("Web Form Field", "fieldtype")
.options.split("\n").indexOf(df.fieldtype)===-1 ? "Data" : df.fieldtype;
doc.description = df.description;
doc["default"] = df["default"];

frm.refresh_field("web_form_fields");
}
});

+ 76
- 1
frappe/website/doctype/web_form/web_form.json Vedi File

@@ -9,11 +9,13 @@
"docstatus": 0,
"doctype": "DocType",
"document_type": "Document",
"editable_grid": 0,
"fields": [
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "title",
"fieldtype": "Data",
"hidden": 0,
@@ -38,6 +40,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "route",
"fieldtype": "Data",
"hidden": 0,
@@ -63,6 +66,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "doc_type",
"fieldtype": "Link",
"hidden": 0,
@@ -88,6 +92,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "module",
"fieldtype": "Link",
"hidden": 1,
@@ -114,6 +119,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break_4",
"fieldtype": "Column Break",
"hidden": 0,
@@ -137,6 +143,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "is_standard",
"fieldtype": "Check",
"hidden": 0,
@@ -162,6 +169,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "published",
"fieldtype": "Check",
"hidden": 0,
@@ -186,6 +194,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "login_required",
"fieldtype": "Check",
"hidden": 0,
@@ -210,6 +219,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "login_required",
"fieldname": "allow_edit",
"fieldtype": "Check",
@@ -235,6 +245,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "login_required",
"fieldname": "allow_multiple",
"fieldtype": "Check",
@@ -260,6 +271,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "allow_multiple",
"fieldname": "allow_delete",
"fieldtype": "Check",
@@ -286,6 +298,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "login_required",
"fieldname": "allow_comments",
"fieldtype": "Check",
@@ -311,6 +324,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "fields",
"fieldtype": "Section Break",
"hidden": 0,
@@ -335,6 +349,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "introduction_text",
"fieldtype": "Text",
"hidden": 0,
@@ -359,6 +374,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "web_form_fields",
"fieldtype": "Table",
"hidden": 0,
@@ -384,6 +400,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "actions",
"fieldtype": "Section Break",
"hidden": 0,
@@ -408,6 +425,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"description": "Message to be displayed on successful completion",
"fieldname": "success_message",
"fieldtype": "Text",
@@ -433,6 +451,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"description": "Go to this url after completing the form.",
"fieldname": "success_url",
"fieldtype": "Data",
@@ -454,10 +473,64 @@
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 1,
"columns": 0,
"fieldname": "sidebar_settings",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Sidebar Settings",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "sidebar_items",
"fieldtype": "Table",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Sidebar Items",
"length": 0,
"no_copy": 0,
"options": "Portal Menu Item",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "advanced",
"fieldtype": "Section Break",
"hidden": 0,
@@ -483,6 +556,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"description": "Text to be displayed for Link to Web Page if this form has a web page. Link route will be automatically generated based on `page_name` and `parent_website_route`",
"fieldname": "web_page_link_text",
"fieldtype": "Data",
@@ -509,6 +583,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"description": "In JSON as [{\"title\":\"Jobs\", \"name\":\"jobs\"}]",
"fieldname": "breadcrumbs",
"fieldtype": "Code",
@@ -543,7 +618,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2016-06-24 15:37:23.369646",
"modified": "2016-09-13 13:08:13.720070",
"modified_by": "Administrator",
"module": "Website",
"name": "Web Form",


+ 36
- 31
frappe/website/doctype/web_form/web_form.py Vedi File

@@ -19,6 +19,7 @@ class WebForm(WebsiteGenerator):
)

def onload(self):
super(WebForm, self).onload()
if self.is_standard and not frappe.conf.developer_mode:
self.use_meta_fields()

@@ -31,9 +32,10 @@ class WebForm(WebsiteGenerator):
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 convert_links_to_selects(self):
def reset_field_parent_and_convert_links_to_selects(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"
@@ -45,7 +47,7 @@ class WebForm(WebsiteGenerator):

else:
df.options = "\n".join([""] + options)
def use_meta_fields(self):
'''Override default properties for standard web forms'''
meta = frappe.get_meta(self.doc_type)
@@ -107,8 +109,8 @@ def get_context(context):
frappe.form_dict.is_web_form = 1
logged_in = frappe.session.user != "Guest"

args, delimeter = make_route_string(frappe.form_dict)
context.args = args
doc, delimeter = make_route_string(frappe.form_dict)
context.doc = doc
context.delimeter = delimeter

# check permissions
@@ -118,7 +120,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.convert_links_to_selects()
self.reset_field_parent_and_convert_links_to_selects()

if self.is_standard:
self.use_meta_fields()
@@ -160,7 +162,6 @@ def get_context(context):

context.parents = self.get_parents(context)

context.types = [f.fieldtype for f in self.web_form_fields]
if context.success_message:
context.success_message = context.success_message.replace("\n",
"<br>").replace("'", "\'")
@@ -193,14 +194,20 @@ def get_context(context):
def get_layout(self):
layout = []
for df in self.web_form_fields:
if df.fieldtype=="Section Break" or not layout:
layout.append([])
if not layout:
layout.append({'columns': []})

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

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

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

if df.fieldtype not in ("Section Break", "Column Break"):
layout[-1][-1].append(df)
layout[-1]['columns'][-1].append(df)

return layout

@@ -215,40 +222,38 @@ def get_context(context):
return parents

@frappe.whitelist(allow_guest=True)
def accept():
args = frappe.form_dict
def accept(web_form, data):
data = frappe._dict(json.loads(data))
files = []

web_form = frappe.get_doc("Web Form", args.web_form)
if args.doctype != web_form.doc_type:
web_form = frappe.get_doc("Web Form", web_form)
if data.doctype != web_form.doc_type:
frappe.throw(_("Invalid Request"))

elif args.name and not web_form.allow_edit:
elif data.name and not web_form.allow_edit:
frappe.throw(_("You are not allowed to update this Web Form Document"))

if args.name:
if data.name:
# update
doc = frappe.get_doc(args.doctype, args.name)
doc = frappe.get_doc(data.doctype, data.name)
else:
# insert
doc = frappe.new_doc(args.doctype)
doc = frappe.new_doc(data.doctype)

# set values
for fieldname, value in args.iteritems():
if fieldname not in ("web_form", "cmd", "owner"):
if value and value.startswith("{"):
try:
filedata = json.loads(value)
if "__file_attachment" in filedata:
files.append((fieldname, filedata))
continue
for fieldname, value in data.iteritems():
if value and isinstance(value, dict):
try:
if "__file_attachment" in value:
files.append((fieldname, value))
continue

except ValueError:
pass
except ValueError:
pass

doc.set(fieldname, value)
doc.set(fieldname, value)

if args.name:
if doc.name:
if has_web_form_permission(doc.doctype, doc.name, "write"):
doc.save(ignore_permissions=True)
else:


+ 18
- 6
frappe/website/doctype/web_form_field/web_form_field.json Vedi File

@@ -14,16 +14,18 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "fieldname",
"columns": 0,
"fieldname": "fieldtype",
"fieldtype": "Select",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Fieldname",
"label": "Fieldtype",
"length": 0,
"no_copy": 0,
"options": "Attach\nCheck\nData\nDate\nDatetime\nHTML\nLink\nSelect\nText\nTable\nSection Break\nColumn Break",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
@@ -38,17 +40,17 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "fieldtype",
"columns": 0,
"fieldname": "fieldname",
"fieldtype": "Select",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Fieldtype",
"label": "Fieldname",
"length": 0,
"no_copy": 0,
"options": "Attach\nCheck\nData\nDate\nDatetime\nHTML\nLink\nSelect\nText\nSection Break\nColumn Break",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
@@ -63,6 +65,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "label",
"fieldtype": "Data",
"hidden": 0,
@@ -87,6 +90,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "reqd",
"fieldtype": "Check",
"hidden": 0,
@@ -111,6 +115,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "read_only",
"fieldtype": "Check",
"hidden": 0,
@@ -135,6 +140,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "hidden",
"fieldtype": "Check",
"hidden": 0,
@@ -159,6 +165,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break_4",
"fieldtype": "Column Break",
"hidden": 0,
@@ -182,6 +189,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "options",
"fieldtype": "Text",
"hidden": 0,
@@ -206,6 +214,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "section_break_6",
"fieldtype": "Section Break",
"hidden": 0,
@@ -229,6 +238,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "description",
"fieldtype": "Text",
"hidden": 0,
@@ -253,6 +263,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break_8",
"fieldtype": "Column Break",
"hidden": 0,
@@ -276,6 +287,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "default",
"fieldtype": "Data",
"hidden": 0,
@@ -307,7 +319,7 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2016-07-11 03:28:09.794347",
"modified": "2016-09-13 12:39:31.889290",
"modified_by": "Administrator",
"module": "Website",
"name": "Web Form Field",


Caricamento…
Annulla
Salva