@@ -214,6 +214,8 @@ def set_user(username): | |||||
local.session.user = username | local.session.user = username | ||||
local.session.sid = username | local.session.sid = username | ||||
local.cache = {} | local.cache = {} | ||||
local.form_dict = _dict() | |||||
local.jenv = None | |||||
local.session.data = {} | local.session.data = {} | ||||
local.user = User(username) | local.user = User(username) | ||||
local.role_permissions = {} | local.role_permissions = {} | ||||
@@ -10,7 +10,8 @@ frappe.upload = { | |||||
+ __('Upload a file') + '</a> | <a class="action-link" href="#"><i class="icon-link"></i> ' | + __('Upload a file') + '</a> | <a class="action-link" href="#"><i class="icon-link"></i> ' | ||||
+ __('Attach as web link') + '</a></p>\ | + __('Attach as web link') + '</a></p>\ | ||||
<div class="action-attach-input">\ | <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>\ | ||||
<div class="action-link-input" style="display: none; margin-top: 7px;">\ | <div class="action-link-input" style="display: none; margin-top: 7px;">\ | ||||
<input class="form-control" style="max-width: 300px;" type="text" name="file_url" />\ | <input class="form-control" style="max-width: 300px;" type="text" name="file_url" />\ | ||||
@@ -5,11 +5,19 @@ | |||||
{% endblock %} | {% endblock %} | ||||
{% block content %} | {% 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"> | <div class="alert alert-info"> | ||||
{{ _("Please login to create a new {0}").format(_(doc_type)) }} | {{ _("Please login to create a new {0}").format(_(doc_type)) }} | ||||
</div> | </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) %} | {% elif (login_required and doc_name and not params.name) %} | ||||
<div class="alert alert-info"> | <div class="alert alert-info"> | ||||
{{ _("{0} already exists").format(_(doc_type)) }} | {{ _("{0} already exists").format(_(doc_type)) }} | ||||
@@ -38,6 +46,19 @@ | |||||
{% endfor %} | {% endfor %} | ||||
</div> | </div> | ||||
{% else %} | {% 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> | <div class="form-message alert alert-info hide"></div> | ||||
<form class="form-horizontal" role="form" | <form class="form-horizontal" role="form" | ||||
data-web-form="{{ name }}"> | data-web-form="{{ name }}"> | ||||
@@ -47,51 +68,60 @@ | |||||
<input type="hidden" name="name" value="{{ params.name }}"> | <input type="hidden" name="name" value="{{ params.name }}"> | ||||
{%- endif %} | {%- endif %} | ||||
{% for field in web_form_fields %} | {% 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"> | <div class="form-group"> | ||||
<label for="{{ field.fieldname }}" class="col-sm-3 control-label"> | |||||
{{ field.label }}</label> | |||||
{{ label(field) }} | |||||
<div class="col-sm-9"> | <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> | ||||
</div> | </div> | ||||
{% elif field.fieldtype=="Select" %} | {% elif field.fieldtype=="Select" %} | ||||
<div class="form-group"> | <div class="form-group"> | ||||
<label for="{{ field.fieldname }}" class="col-sm-3 control-label"> | |||||
{{ field.label }}</label> | |||||
{{ label(field) }} | |||||
<div class="col-sm-9"> | <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") %} | {% for option in field.options.split("\n") %} | ||||
<option value="{{ option }}" | <option value="{{ option }}" | ||||
"{{ doc and doc.get(field.fieldname)==option and 'selected' or '' }}"> | |||||
"value(field)==option and 'selected' or '' }}"> | |||||
{{ option }}</option> | {{ option }}</option> | ||||
{% endfor %} | {% endfor %} | ||||
</select> | </select> | ||||
{% if field.description -%} | |||||
<span class="help-block">{{ field.description }}</span> | |||||
{%- endif %} | |||||
{{ help(field) }} | |||||
</div> | </div> | ||||
</div> | </div> | ||||
{% elif field.fieldtype=="Text" %} | {% elif field.fieldtype=="Text" %} | ||||
<div class="form-group"> | <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"> | <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 %} | {%- 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> | ||||
</div> | </div> | ||||
{% elif field.fieldtype=="Check" %} | {% elif field.fieldtype=="Check" %} | ||||
@@ -104,6 +134,7 @@ | |||||
"{{ doc and doc.get(field.fieldname) and 'checked' or '' }}"> | "{{ doc and doc.get(field.fieldname) and 'checked' or '' }}"> | ||||
{{ field.label }} | {{ field.label }} | ||||
</label> | </label> | ||||
{{ help(field) }} | |||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
@@ -116,24 +147,85 @@ | |||||
</div> | </div> | ||||
</div> | </div> | ||||
</form> | </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 %} | {% endif %} | ||||
{% endblock %} | {% endblock %} | ||||
{% block script %} | {% block script %} | ||||
<script> | <script> | ||||
frappe.ready(function() { | frappe.ready(function() { | ||||
window.file_reading = false; | |||||
var $form = $("form[data-web-form='{{ name }}']"); | 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() { | $("form[data-web-form='{{ name }}']").on("submit", function() { | ||||
var args = {}; | 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() { | $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) { | 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({ | frappe.call({ | ||||
@@ -154,10 +246,42 @@ frappe.ready(function() { | |||||
}, 1000); | }, 1000); | ||||
{%- endif %}; | {%- endif %}; | ||||
} | } | ||||
window.saving = false; | |||||
} | } | ||||
}) | |||||
}); | |||||
return 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> | </script> | ||||
{% endblock %} | {% endblock %} |
@@ -100,10 +100,13 @@ login.login_handlers = (function() { | |||||
var login_handlers = { | var login_handlers = { | ||||
200: function(data) { | 200: function(data) { | ||||
if(data.message=="Logged In") { | if(data.message=="Logged In") { | ||||
window.location.href = "desk"; | |||||
window.location.href = get_url_arg("redirect-to") || "/desk"; | |||||
} else if(data.message=="No App") { | } else if(data.message=="No App") { | ||||
if(localStorage) { | 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"); | localStorage.removeItem("last_visited"); | ||||
window.location.href = last_visited; | window.location.href = last_visited; | ||||
} else { | } else { | ||||
@@ -1,7 +1,6 @@ | |||||
{% block title %}{{ title }}{% endblock %} | {% 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 %} | {% block content %} | ||||
<div class="message-content"> | <div class="message-content"> | ||||
@@ -107,6 +107,9 @@ def save_file(fname, content, dt, dn, decode=False): | |||||
if decode: | if decode: | ||||
if isinstance(content, unicode): | if isinstance(content, unicode): | ||||
content = content.encode("utf-8") | content = content.encode("utf-8") | ||||
if "," in content: | |||||
content = content.split(",")[1] | |||||
content = base64.b64decode(content) | content = base64.b64decode(content) | ||||
file_size = check_max_file_size(content) | file_size = check_max_file_size(content) | ||||
@@ -180,6 +183,18 @@ def remove_all(dt, dn): | |||||
except Exception, e: | except Exception, e: | ||||
if e.args[0]!=1054: raise # (temp till for patched) | 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): | def remove_file(fid, attached_to_doctype=None, attached_to_name=None): | ||||
"""Remove file and File Data entry""" | """Remove file and File Data entry""" | ||||
file_name = None | file_name = None | ||||
@@ -52,7 +52,8 @@ def get_allowed_functions_for_jenv(): | |||||
"get_doc": frappe.get_doc, | "get_doc": frappe.get_doc, | ||||
"get_list": frappe.get_list, | "get_list": frappe.get_list, | ||||
"utils": datautils, | "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": \ | "get_visible_columns": \ | ||||
frappe.get_attr("frappe.templates.pages.print.get_visible_columns"), | frappe.get_attr("frappe.templates.pages.print.get_visible_columns"), | ||||
@@ -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 | |||||
} | |||||
] | |||||
}] |
@@ -4,7 +4,61 @@ | |||||
import frappe | import frappe | ||||
import unittest | 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') | test_records = frappe.get_test_records('Web Form') | ||||
class TestWebForm(unittest.TestCase): | 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) |
@@ -18,6 +18,7 @@ frappe.web_form = { | |||||
frappe.ui.form.on("Web Form", "refresh", function(frm) { | frappe.ui.form.on("Web Form", "refresh", function(frm) { | ||||
frappe.web_form.set_fieldname_select(frm); | frappe.web_form.set_fieldname_select(frm); | ||||
cur_frm.set_intro(""); | |||||
if (!frm.doc.__islocal && frm.doc.published) { | if (!frm.doc.__islocal && frm.doc.published) { | ||||
cur_frm.set_intro(__("Published on website at: {0}", | cur_frm.set_intro(__("Published on website at: {0}", | ||||
[repl('<a href="/%(website_route)s" target="_blank">/%(website_route)s</a>', | [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.ui.form.on("Web Form", "doc_type", function(frm) { | ||||
frappe.web_form.set_fieldname_select(frm); | frappe.web_form.set_fieldname_select(frm); | ||||
}); | }); | ||||
@@ -177,6 +177,12 @@ | |||||
"label": "Fields", | "label": "Fields", | ||||
"permlevel": 0 | "permlevel": 0 | ||||
}, | }, | ||||
{ | |||||
"fieldname": "introduction_text", | |||||
"fieldtype": "Text", | |||||
"label": "Introduction", | |||||
"permlevel": 0 | |||||
}, | |||||
{ | { | ||||
"fieldname": "web_form_fields", | "fieldname": "web_form_fields", | ||||
"fieldtype": "Table", | "fieldtype": "Table", | ||||
@@ -193,7 +199,7 @@ | |||||
"is_submittable": 0, | "is_submittable": 0, | ||||
"issingle": 0, | "issingle": 0, | ||||
"istable": 0, | "istable": 0, | ||||
"modified": "2014-09-02 13:52:53.494298", | |||||
"modified": "2014-09-03 14:47:17.181589", | |||||
"modified_by": "Administrator", | "modified_by": "Administrator", | ||||
"module": "Website", | "module": "Website", | ||||
"name": "Web Form", | "name": "Web Form", | ||||
@@ -2,9 +2,10 @@ | |||||
# For license information, please see license.txt | # For license information, please see license.txt | ||||
from __future__ import unicode_literals | from __future__ import unicode_literals | ||||
import frappe | |||||
import frappe, json | |||||
from frappe.website.website_generator import WebsiteGenerator | from frappe.website.website_generator import WebsiteGenerator | ||||
from frappe import _ | from frappe import _ | ||||
from frappe.utils.file_manager import save_file, remove_file_by_url | |||||
class WebForm(WebsiteGenerator): | class WebForm(WebsiteGenerator): | ||||
template = "templates/generators/web_form.html" | template = "templates/generators/web_form.html" | ||||
@@ -31,18 +32,35 @@ class WebForm(WebsiteGenerator): | |||||
if frappe.form_dict.name: | if frappe.form_dict.name: | ||||
context.doc = frappe.get_doc(self.doc_type, 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 | return context | ||||
@frappe.whitelist(allow_guest=True) | @frappe.whitelist(allow_guest=True) | ||||
def accept(): | def accept(): | ||||
args = frappe.form_dict | args = frappe.form_dict | ||||
files = [] | |||||
if args.name: | if args.name: | ||||
# update | |||||
doc = frappe.get_doc(args.doctype, args.name) | doc = frappe.get_doc(args.doctype, args.name) | ||||
else: | else: | ||||
# insert | |||||
doc = frappe.new_doc(args.doctype) | doc = frappe.new_doc(args.doctype) | ||||
# set values | |||||
for fieldname, value in args.iteritems(): | for fieldname, value in args.iteritems(): | ||||
if fieldname not in ("web_form", "cmd"): | 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) | doc.set(fieldname, value) | ||||
if args.name: | if args.name: | ||||
@@ -59,3 +77,21 @@ def accept(): | |||||
frappe.throw(_("You must login to submit this form")) | frappe.throw(_("You must login to submit this form")) | ||||
doc.insert(ignore_permissions = True) | 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() |
@@ -36,7 +36,7 @@ | |||||
"in_list_view": 1, | "in_list_view": 1, | ||||
"label": "Fieldtype", | "label": "Fieldtype", | ||||
"no_copy": 0, | "no_copy": 0, | ||||
"options": "Attach\nCheck\nData\nHTML\nSelect\nText", | |||||
"options": "Attach\nCheck\nData\nDate\nDatetime\nHTML\nSelect\nText", | |||||
"permlevel": 0, | "permlevel": 0, | ||||
"print_hide": 0, | "print_hide": 0, | ||||
"read_only": 0, | "read_only": 0, | ||||
@@ -69,6 +69,18 @@ | |||||
"label": "Mandatory", | "label": "Mandatory", | ||||
"permlevel": 0 | "permlevel": 0 | ||||
}, | }, | ||||
{ | |||||
"fieldname": "read_only", | |||||
"fieldtype": "Check", | |||||
"label": "Read Only", | |||||
"permlevel": 0 | |||||
}, | |||||
{ | |||||
"fieldname": "hidden", | |||||
"fieldtype": "Check", | |||||
"label": "Hidden", | |||||
"permlevel": 0 | |||||
}, | |||||
{ | { | ||||
"allow_on_submit": 0, | "allow_on_submit": 0, | ||||
"fieldname": "column_break_4", | "fieldname": "column_break_4", | ||||
@@ -182,7 +194,7 @@ | |||||
"is_submittable": 0, | "is_submittable": 0, | ||||
"issingle": 0, | "issingle": 0, | ||||
"istable": 1, | "istable": 1, | ||||
"modified": "2014-09-01 14:14:40.425829", | |||||
"modified": "2014-09-03 15:47:51.643284", | |||||
"modified_by": "Administrator", | "modified_by": "Administrator", | ||||
"module": "Website", | "module": "Website", | ||||
"name": "Web Form Field", | "name": "Web Form Field", | ||||
@@ -3,6 +3,7 @@ | |||||
from __future__ import unicode_literals | from __future__ import unicode_literals | ||||
import frappe | import frappe | ||||
from frappe import _ | |||||
from frappe.utils import cstr | from frappe.utils import cstr | ||||
import mimetypes, json | import mimetypes, json | ||||
from werkzeug.wrappers import Response | from werkzeug.wrappers import Response | ||||
@@ -36,10 +37,10 @@ def render(path, http_status_code=None): | |||||
try: | try: | ||||
data = render_page(path) | data = render_page(path) | ||||
except frappe.PermissionError, e: | except frappe.PermissionError, e: | ||||
data, http_status_code = render_403(e) | |||||
data, http_status_code = render_403(e, path) | |||||
except frappe.PermissionError, e: | except frappe.PermissionError, e: | ||||
data, http_status_code = render_403(e) | |||||
data, http_status_code = render_403(e, path) | |||||
except Exception: | except Exception: | ||||
path = "error" | path = "error" | ||||
@@ -49,10 +50,13 @@ def render(path, http_status_code=None): | |||||
return build_response(path, data, http_status_code or 200) | return build_response(path, data, http_status_code or 200) | ||||
def render_403(e): | |||||
def render_403(e, pathname): | |||||
path = "message" | 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 | return render_page(path), e.http_status_code | ||||
def get_doctype_from_path(path): | def get_doctype_from_path(path): | ||||