浏览代码

added test cases #807

version-14
Rushabh Mehta 11 年前
父节点
当前提交
358c65b715
共有 14 个文件被更改,包括 363 次插入55 次删除
  1. +2
    -0
      frappe/__init__.py
  2. +2
    -1
      frappe/public/js/frappe/upload.js
  3. +157
    -33
      frappe/templates/generators/web_form.html
  4. +5
    -2
      frappe/templates/includes/login.js
  5. +1
    -2
      frappe/templates/pages/message.html
  6. +15
    -0
      frappe/utils/file_manager.py
  7. +2
    -1
      frappe/utils/jinja.py
  8. +48
    -6
      frappe/website/doctype/web_form/test_records.json
  9. +55
    -1
      frappe/website/doctype/web_form/test_web_form.py
  10. +9
    -0
      frappe/website/doctype/web_form/web_form.js
  11. +7
    -1
      frappe/website/doctype/web_form/web_form.json
  12. +37
    -1
      frappe/website/doctype/web_form/web_form.py
  13. +14
    -2
      frappe/website/doctype/web_form_field/web_form_field.json
  14. +9
    -5
      frappe/website/render.py

+ 2
- 0
frappe/__init__.py 查看文件

@@ -214,6 +214,8 @@ def set_user(username):
local.session.user = username
local.session.sid = username
local.cache = {}
local.form_dict = _dict()
local.jenv = None
local.session.data = {}
local.user = User(username)
local.role_permissions = {}


+ 2
- 1
frappe/public/js/frappe/upload.js 查看文件

@@ -10,7 +10,8 @@ frappe.upload = {
+ __('Upload a file') + '</a> | <a class="action-link" href="#"><i class="icon-link"></i> '
+ __('Attach as web link') + '</a></p>\
<div class="action-attach-input">\
<input class="alert alert-info" style="padding: 7px; margin: 7px 0px;" type="file" name="filedata" />\
<input class="alert alert-info" style="padding: 7px; margin: 7px 0px;" \
type="file" name="filedata" />\
</div>\
<div class="action-link-input" style="display: none; margin-top: 7px;">\
<input class="form-control" style="max-width: 300px;" type="text" name="file_url" />\


+ 157
- 33
frappe/templates/generators/web_form.html 查看文件

@@ -5,11 +5,19 @@
{% endblock %}

{% block content %}

{% if login_required and user=="Guest" %}
{% if introduction_text %}
<p class="lead">{{ introduction_text }}</p>
<hr>
{% endif %}
{% if login_required and frappe.user=="Guest" %}
<div class="alert alert-info">
{{ _("Please login to create a new {0}").format(_(doc_type)) }}
</div>
<p>
<a href="/login?redirect-to=/{{ pathname }}" class="btn btn-primary">
{{ _("Login") }}
</a>
</p>
{% elif (login_required and doc_name and not params.name) %}
<div class="alert alert-info">
{{ _("{0} already exists").format(_(doc_type)) }}
@@ -38,6 +46,19 @@
{% endfor %}
</div>
{% else %}

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

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

{%- macro help(field) -%}
{% if field.description -%}
<span class="help-block">{{ field.description }}</span>
{%- endif -%}
{%- endmacro %}

{% macro label(field) %}<label for="{{ field.fieldname }}" class="col-sm-3 control-label">{{ field.label }}</label>{% endmacro %}

<div class="form-message alert alert-info hide"></div>
<form class="form-horizontal" role="form"
data-web-form="{{ name }}">
@@ -47,51 +68,60 @@
<input type="hidden" name="name" value="{{ params.name }}">
{%- endif %}
{% for field in web_form_fields %}
{% if field.fieldtype=="Data" %}
{% if field.hidden %}
<input type="hidden"
name="{{ field.fieldname }}" value="{{ field.default }}">
{% elif field.fieldtype in ("Data", "Date", "Datetime") %}
<div class="form-group">
<label for="{{ field.fieldname }}" class="col-sm-3 control-label">
{{ field.label }}</label>
{{ label(field) }}
<div class="col-sm-9">
<input type="text" class="form-control" name="{{ field.fieldname }}"
id="{{ field.fieldname }}" placeholder="{{ field.placeholder or '' }}"
{{ field.reqd and "required" or "" }} data-label="{{ field.label }}"
value="{{ doc and doc.get(field.fieldname) or '' }}">
{% if field.description -%}
<span class="help-block">{{ field.description }}</span>
{%- endif %}
<input type="text" class="form-control" {{ properties(field) }}
value="{{ value(field) }}">
{{ help(field) }}
</div>
</div>
{% elif field.fieldtype=="Select" %}
<div class="form-group">
<label for="{{ field.fieldname }}" class="col-sm-3 control-label">
{{ field.label }}</label>
{{ label(field) }}
<div class="col-sm-9">
<select class="form-control" name="{{ field.fieldname }}"
data-label="{{ field.label }}"
id="{{ field.fieldname }}" {{ field.reqd and "required" or "" }}>
<select class="form-control" {{ properties(field) }}>
{% for option in field.options.split("\n") %}
<option value="{{ option }}"
"{{ doc and doc.get(field.fieldname)==option and 'selected' or '' }}">
"value(field)==option and 'selected' or '' }}">
{{ option }}</option>
{% endfor %}
</select>
{% if field.description -%}
<span class="help-block">{{ field.description }}</span>
{%- endif %}
{{ help(field) }}
</div>
</div>
{% elif field.fieldtype=="Text" %}
<div class="form-group">
<label for="{{ field.fieldname }}" class="col-sm-3 control-label">
{{ field.label }}</label>
{{ label(field) }}
<div class="col-sm-9">
<textarea class="form-control" style="height: 100px;"
{{ properties(field) }}>{{ value(field) }}</textarea>
{{ help(field) }}
</div>
</div>
{% elif field.fieldtype=="Attach" %}
<div class="form-group">
{{ label(field) }}
<div class="col-sm-9">
<textarea class="form-control" name="{{ field.fieldname }}"
id="{{ field.fieldname }}" style="height: 100px;"
data-label="{{ field.label }}"
{{ field.reqd and "required" or "" }}>{{ doc and doc.get(field.fieldname) or '' }}</textarea>
{% if field.description -%}
<span class="help-block">{{ field.description }}</span>
{% if value(field) -%}
<p>
<i class="icon-paperclip"></i>
<a href="{{ doc.get(field.fieldname) }}" target="blank">
{{ doc.get(field.fieldname) }}
</a>
<br><button class="btn btn-small btn-default
change-attach" style="margin-top: 5px;">Change</button>
</p>
{%- endif %}
<p class="{{ value(field) and 'hide' or '' }} attach-input-wrap">
<input type="file" style="margin-top: 7px;"
{{ properties(field) }}>
</p>
{{ help(field) }}
</div>
</div>
{% elif field.fieldtype=="Check" %}
@@ -104,6 +134,7 @@
"{{ doc and doc.get(field.fieldname) and 'checked' or '' }}">
{{ field.label }}
</label>
{{ help(field) }}
</div>
</div>
</div>
@@ -116,24 +147,85 @@
</div>
</div>
</form>
{% if allow_comments -%}
<div class="row">
<div class="col-sm-offset-3 col-sm-9">
<hr>
<h3>{{ _("Comments") }}</h3>
{% include 'templates/includes/comments.html' %}
</div>
</div>
{%- endif %}
{% endif %}
{% endblock %}

{% block script %}
<script>
frappe.ready(function() {
window.file_reading = false;
var $form = $("form[data-web-form='{{ name }}']");

// read file attachment
$form.on("change", "[type='file']", function() {
var $input = $(this);
if($input.attr("type")==="file") {
var input = $input.get(0);
var reader = new FileReader();

input.filedata = null;
if(input.files.length) {
file = input.files[0];
window.file_reading = true;
reader.onload = function(e) {
input.filedata = {
"__file_attachment": 1,
"filename": file.name,
"dataurl": reader.result
};
window.file_reading = false;
}

reader.readAsDataURL(file);
}
}
});

// change attach
$form.on("click", ".change-attach", function() {
$(this).parent().addClass("hide")
.parent().find(".attach-input-wrap").removeClass("hide");

return false;
});

$("form[data-web-form='{{ name }}']").on("submit", function() {
var args = {};
if(window.saving)
return;
window.saving = true;

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

$form.find("[name]").each(function() {
var $input = $(this), val = $input.val();
var $input = $(this);
if($input.attr("type")==="file") {
var val = $input.get(0).filedata;
} else {
var val = $input.val();
}

if($input.prop("required") && val===undefined) {
frappe.msgprint($)
frappe.msgprint(__("{0} is required",
$input.attr("data-label")));
window.saving = false;
throw "mandatory missing";
}
args[$(this).attr("name")] = $(this).val();

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

frappe.call({
@@ -154,10 +246,42 @@ frappe.ready(function() {
}, 1000);
{%- endif %};
}
window.saving = false;
}
})
});

return false;
});

// 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.date_format.replace('yyyy', 'yy') }}",
})

{% endif %}

{% 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='Date']").datetimepicker({
altFormat:'yy-mm-dd',
changeYear: true,
yearRange: "-70Y:+10Y",
dateFormat: "{{ frappe.date_format.replace('yyyy', 'yy') }}",
})
{% endif %}

{% for f in web_form_fields %}
{% endfor %}

});
</script>
{% endblock %}

+ 5
- 2
frappe/templates/includes/login.js 查看文件

@@ -100,10 +100,13 @@ login.login_handlers = (function() {
var login_handlers = {
200: function(data) {
if(data.message=="Logged In") {
window.location.href = "desk";
window.location.href = get_url_arg("redirect-to") || "/desk";
} else if(data.message=="No App") {
if(localStorage) {
var last_visited = localStorage.getItem("last_visited") || "/index";
var last_visited =
localStorage.getItem("last_visited")
|| get_url_arg("redirect-to")
|| "/index";
localStorage.removeItem("last_visited");
window.location.href = last_visited;
} else {


+ 1
- 2
frappe/templates/pages/message.html 查看文件

@@ -1,7 +1,6 @@
{% block title %}{{ title }}{% endblock %}

{% block header %}<span {% if success!=None %}class="text-{{ 'success' if success else 'danger'}}"{% endif %}>
{{ title }}</span>{% endblock %}
{% block header %}{{ title }}{% endblock %}

{% block content %}
<div class="message-content">


+ 15
- 0
frappe/utils/file_manager.py 查看文件

@@ -107,6 +107,9 @@ def save_file(fname, content, dt, dn, decode=False):
if decode:
if isinstance(content, unicode):
content = content.encode("utf-8")

if "," in content:
content = content.split(",")[1]
content = base64.b64decode(content)

file_size = check_max_file_size(content)
@@ -180,6 +183,18 @@ def remove_all(dt, dn):
except Exception, e:
if e.args[0]!=1054: raise # (temp till for patched)

def remove_file_by_url(file_url, doctype=None, name=None):
if doctype and name:
fid = frappe.db.get_value("File Data", {"file_url": file_url,
"attached_to_doctype": doctype, "attached_to_name": name})
else:
fid = frappe.db.get_value("File Data", {"file_url": file_url})

print file_url, doctype, name, fid

if fid:
return remove_file(fid)

def remove_file(fid, attached_to_doctype=None, attached_to_name=None):
"""Remove file and File Data entry"""
file_name = None


+ 2
- 1
frappe/utils/jinja.py 查看文件

@@ -52,7 +52,8 @@ def get_allowed_functions_for_jenv():
"get_doc": frappe.get_doc,
"get_list": frappe.get_list,
"utils": datautils,
"user": frappe.session.user
"user": frappe.session.user,
"date_format": frappe.db.get_default("date_format") or "yyyy-mm-dd"
},
"get_visible_columns": \
frappe.get_attr("frappe.templates.pages.print.get_visible_columns"),


+ 48
- 6
frappe/website/doctype/web_form/test_records.json 查看文件

@@ -1,6 +1,48 @@
[
{
"doctype": "Web Form",
"name": "_Test Web Form 1"
}
]
[{
"allow_comments": 0,
"allow_edit": 1,
"allow_multiple": 1,
"doc_type": "Event",
"docstatus": 0,
"doctype": "Web Form",
"introduction_text": "Add events",
"login_required": 1,
"name": "manage-events",
"owner": "Administrator",
"page_name": "manage-events",
"published": 1,
"success_url": "/manage-events",
"title": "Manage Events",
"web_form_fields": [
{
"doctype": "Web Form Field",
"fieldname": "subject",
"fieldtype": "Data",
"hidden": 0,
"idx": 1,
"label": "Title",
"read_only": 0,
"reqd": 1
},
{
"doctype": "Web Form Field",
"fieldname": "starts_on",
"fieldtype": "Date",
"hidden": 0,
"idx": 2,
"label": "Event Date",
"read_only": 0,
"reqd": 1
},
{
"doctype": "Web Form Field",
"fieldname": "description",
"fieldtype": "Text",
"hidden": 0,
"idx": 3,
"label": "Description",
"read_only": 0,
"reqd": 0
}
]
}]

+ 55
- 1
frappe/website/doctype/web_form/test_web_form.py 查看文件

@@ -4,7 +4,61 @@
import frappe
import unittest

from frappe.website.render import build_page
from frappe.website.doctype.web_form.web_form import accept

test_records = frappe.get_test_records('Web Form')

class TestWebForm(unittest.TestCase):
pass
def setUp(self):
frappe.conf.disable_website_cache = True

def tearDown(self):
frappe.conf.disable_website_cache = False

def test_basic(self):
frappe.set_user("Guest")
html = build_page("manage-events")
self.assertTrue("Please login to create a new Event" in html)

def test_logged_in(self):
frappe.set_user("Administrator")
html = build_page("manage-events")
self.assertFalse("Please login to create a new Event" in html)
self.assertTrue('"/manage-events?new=1"' in html)

def test_new(self):
frappe.set_user("Administrator")
frappe.local.form_dict.new = 1
html = build_page("manage-events")
self.assertTrue('name="subject"' in html)

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()

self.event_name = frappe.db.get_value("Event",
{"subject": "_Test Event Web Form"})
self.assertTrue(self.event_name)

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"

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

accept()

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

+ 9
- 0
frappe/website/doctype/web_form/web_form.js 查看文件

@@ -18,6 +18,7 @@ frappe.web_form = {
frappe.ui.form.on("Web Form", "refresh", function(frm) {
frappe.web_form.set_fieldname_select(frm);

cur_frm.set_intro("");
if (!frm.doc.__islocal && frm.doc.published) {
cur_frm.set_intro(__("Published on website at: {0}",
[repl('<a href="/%(website_route)s" target="_blank">/%(website_route)s</a>',
@@ -26,6 +27,14 @@ frappe.ui.form.on("Web Form", "refresh", function(frm) {

});

frappe.ui.form.on("Web Form", "title", function(frm) {
if(frm.doc.__islocal) {
var page_name = frm.doc.title.toLowerCase().replace(/ /g, "-");
frm.set_value("page_name", page_name);
frm.set_value("success_url", "/" + page_name);
}
});

frappe.ui.form.on("Web Form", "doc_type", function(frm) {
frappe.web_form.set_fieldname_select(frm);
});


+ 7
- 1
frappe/website/doctype/web_form/web_form.json 查看文件

@@ -177,6 +177,12 @@
"label": "Fields",
"permlevel": 0
},
{
"fieldname": "introduction_text",
"fieldtype": "Text",
"label": "Introduction",
"permlevel": 0
},
{
"fieldname": "web_form_fields",
"fieldtype": "Table",
@@ -193,7 +199,7 @@
"is_submittable": 0,
"issingle": 0,
"istable": 0,
"modified": "2014-09-02 13:52:53.494298",
"modified": "2014-09-03 14:47:17.181589",
"modified_by": "Administrator",
"module": "Website",
"name": "Web Form",


+ 37
- 1
frappe/website/doctype/web_form/web_form.py 查看文件

@@ -2,9 +2,10 @@
# For license information, please see license.txt

from __future__ import unicode_literals
import frappe
import frappe, json
from frappe.website.website_generator import WebsiteGenerator
from frappe import _
from frappe.utils.file_manager import save_file, remove_file_by_url

class WebForm(WebsiteGenerator):
template = "templates/generators/web_form.html"
@@ -31,18 +32,35 @@ class WebForm(WebsiteGenerator):
if frappe.form_dict.name:
context.doc = frappe.get_doc(self.doc_type, frappe.form_dict.name)

context.types = [f.fieldtype for f in self.web_form_fields]

return context

@frappe.whitelist(allow_guest=True)
def accept():
args = frappe.form_dict
files = []

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

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

except ValueError:
pass

doc.set(fieldname, value)

if args.name:
@@ -59,3 +77,21 @@ def accept():
frappe.throw(_("You must login to submit this form"))

doc.insert(ignore_permissions = True)

# add files
if files:
for f in files:
fieldname, filedata = f

# remove earlier attachmed file (if exists)
if doc.get(fieldname):
remove_file_by_url(doc.get(fieldname), doc.doctype, doc.name)

# save new file
filedoc = save_file(filedata["filename"], filedata["dataurl"],
doc.doctype, doc.name, decode=True)

# update values
doc.set(fieldname, filedoc.file_url)

doc.save()

+ 14
- 2
frappe/website/doctype/web_form_field/web_form_field.json 查看文件

@@ -36,7 +36,7 @@
"in_list_view": 1,
"label": "Fieldtype",
"no_copy": 0,
"options": "Attach\nCheck\nData\nHTML\nSelect\nText",
"options": "Attach\nCheck\nData\nDate\nDatetime\nHTML\nSelect\nText",
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
@@ -69,6 +69,18 @@
"label": "Mandatory",
"permlevel": 0
},
{
"fieldname": "read_only",
"fieldtype": "Check",
"label": "Read Only",
"permlevel": 0
},
{
"fieldname": "hidden",
"fieldtype": "Check",
"label": "Hidden",
"permlevel": 0
},
{
"allow_on_submit": 0,
"fieldname": "column_break_4",
@@ -182,7 +194,7 @@
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"modified": "2014-09-01 14:14:40.425829",
"modified": "2014-09-03 15:47:51.643284",
"modified_by": "Administrator",
"module": "Website",
"name": "Web Form Field",


+ 9
- 5
frappe/website/render.py 查看文件

@@ -3,6 +3,7 @@

from __future__ import unicode_literals
import frappe
from frappe import _
from frappe.utils import cstr
import mimetypes, json
from werkzeug.wrappers import Response
@@ -36,10 +37,10 @@ def render(path, http_status_code=None):
try:
data = render_page(path)
except frappe.PermissionError, e:
data, http_status_code = render_403(e)
data, http_status_code = render_403(e, path)

except frappe.PermissionError, e:
data, http_status_code = render_403(e)
data, http_status_code = render_403(e, path)

except Exception:
path = "error"
@@ -49,10 +50,13 @@ def render(path, http_status_code=None):
return build_response(path, data, http_status_code or 200)


def render_403(e):
def render_403(e, pathname):
path = "message"
frappe.local.message = "<p><strong>{error}</strong></p><p>Did you log out?</p>".format(error=cstr(e))
frappe.local.message_title = "Not Permitted"
frappe.local.message = """<p><strong>{error}</strong></p>
<p>
<a href="/login?redirect-to=/{pathname}" class="btn btn-primary>{login}</a>
</p>""".format(error=cstr(e), login=_("Login"), pathname=pathname)
frappe.local.message_title = _("Not Permitted")
return render_page(path), e.http_status_code

def get_doctype_from_path(path):


正在加载...
取消
保存