mirror of
https://github.com/erpnext/foundation.git
synced 2026-10-16 18:00:47 +02:00
Add webform css and add event loop on homepage
This commit is contained in:
1710
foundation/public/css/bootstrap-for-webform.css
vendored
Normal file
1710
foundation/public/css/bootstrap-for-webform.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,5 @@
|
|||||||
@import "reset.css";
|
@import "reset.css";
|
||||||
|
/*@import (css) "bootstrap-temp.css";*/
|
||||||
.indicator,
|
.indicator,
|
||||||
.indicator-right {
|
.indicator-right {
|
||||||
background: none;
|
background: none;
|
||||||
@@ -360,7 +361,6 @@ hr {
|
|||||||
font-size: 0.75rem;
|
font-size: 0.75rem;
|
||||||
}
|
}
|
||||||
.footer-end a {
|
.footer-end a {
|
||||||
text-decoration: underline;
|
|
||||||
color: #8D99A6;
|
color: #8D99A6;
|
||||||
}
|
}
|
||||||
.footer-end a:hover {
|
.footer-end a:hover {
|
||||||
@@ -371,6 +371,47 @@ hr {
|
|||||||
margin-right: .5em;
|
margin-right: .5em;
|
||||||
}
|
}
|
||||||
/* loaned from bootstrap*/
|
/* loaned from bootstrap*/
|
||||||
|
caption {
|
||||||
|
padding-top: 8px;
|
||||||
|
padding-bottom: 8px;
|
||||||
|
color: #8d99a6;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
th {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
.note-popover .popover-content > .btn-group,
|
||||||
|
.panel-heading.note-toolbar > .btn-group {
|
||||||
|
margin-top: 5px;
|
||||||
|
margin-right: 5px;
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
.btn-group,
|
||||||
|
.btn-group-vertical {
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
.note-popover .popover-content,
|
||||||
|
.panel-heading.note-toolbar {
|
||||||
|
padding: 0 0 5px 5px;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
.panel-default > .panel-heading {
|
||||||
|
color: #333;
|
||||||
|
background-color: #F7FAFC;
|
||||||
|
border-color: #d1d8dd;
|
||||||
|
}
|
||||||
|
.panel-heading,
|
||||||
|
.panel-body {
|
||||||
|
padding-left: 1rem;
|
||||||
|
}
|
||||||
|
.panel-heading {
|
||||||
|
padding: .5rem 1rem;
|
||||||
|
border-bottom: 1px solid transparent;
|
||||||
|
border-top-left-radius: .25em;
|
||||||
|
border-top-right-radius: .25em;
|
||||||
|
}
|
||||||
.modal-open .modal {
|
.modal-open .modal {
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
@@ -467,27 +508,6 @@ hr {
|
|||||||
border: 1px solid transparent;
|
border: 1px solid transparent;
|
||||||
border-radius: .25em;
|
border-radius: .25em;
|
||||||
}
|
}
|
||||||
.table-bordered {
|
|
||||||
border: 1px solid #d1d8dd;
|
|
||||||
}
|
|
||||||
.table-bordered > thead > tr > th,
|
|
||||||
.table-bordered > tbody > tr > th,
|
|
||||||
.table-bordered > tfoot > tr > th,
|
|
||||||
.table-bordered > thead > tr > td,
|
|
||||||
.table-bordered > tbody > tr > td,
|
|
||||||
.table-bordered > tfoot > tr > td {
|
|
||||||
border: 1px solid #d1d8dd;
|
|
||||||
}
|
|
||||||
.table > thead > tr > th,
|
|
||||||
.table > tbody > tr > th,
|
|
||||||
.table > tfoot > tr > th,
|
|
||||||
.table > thead > tr > td,
|
|
||||||
.table > tbody > tr > td,
|
|
||||||
.table > tfoot > tr > td {
|
|
||||||
padding: .5em;
|
|
||||||
vertical-align: top;
|
|
||||||
border-top: 1px solid #EBEFF2;
|
|
||||||
}
|
|
||||||
.btn-block {
|
.btn-block {
|
||||||
display: block;
|
display: block;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@@ -682,6 +702,12 @@ img.blog-cover-image,
|
|||||||
.media-heading {
|
.media-heading {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
.with-border {
|
||||||
|
border: 1px solid #d1d8dd;
|
||||||
|
border-radius: 0.25em;
|
||||||
|
padding: 1rem;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
}
|
||||||
/* individual elements */
|
/* individual elements */
|
||||||
.domain-links {
|
.domain-links {
|
||||||
font-size: 1.5rem;
|
font-size: 1.5rem;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
@import (css) "reset.css";
|
@import (css) "reset.css";
|
||||||
|
/*@import (css) "bootstrap-temp.css";*/
|
||||||
@import "variables.less";
|
@import "variables.less";
|
||||||
@import "indicator.less";
|
@import "indicator.less";
|
||||||
|
|
||||||
@@ -231,9 +232,12 @@ a {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.list-circle {
|
||||||
|
list-style: circle;
|
||||||
|
}
|
||||||
|
|
||||||
.bulleted-list {
|
.bulleted-list {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
list-style: circle;
|
|
||||||
padding-left: 1em;
|
padding-left: 1em;
|
||||||
|
|
||||||
li {
|
li {
|
||||||
@@ -337,7 +341,6 @@ hr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.footer-end a{
|
.footer-end a{
|
||||||
text-decoration: underline;
|
|
||||||
color: @text-muted;
|
color: @text-muted;
|
||||||
&:hover{
|
&:hover{
|
||||||
color: #fff;
|
color: #fff;
|
||||||
@@ -351,6 +354,44 @@ hr {
|
|||||||
|
|
||||||
/* loaned from bootstrap*/
|
/* loaned from bootstrap*/
|
||||||
|
|
||||||
|
caption {
|
||||||
|
padding-top: 8px;
|
||||||
|
padding-bottom: 8px;
|
||||||
|
color: #8d99a6;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
th {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.note-popover .popover-content > .btn-group, .panel-heading.note-toolbar > .btn-group {
|
||||||
|
margin-top: 5px;
|
||||||
|
margin-right: 5px;
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
.btn-group, .btn-group-vertical {
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
.note-popover .popover-content, .panel-heading.note-toolbar {
|
||||||
|
padding: 0 0 5px 5px;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
.panel-default > .panel-heading {
|
||||||
|
color: #333;
|
||||||
|
background-color:@panel-bg;
|
||||||
|
border-color: @border-color;
|
||||||
|
}
|
||||||
|
.panel-heading, .panel-body {
|
||||||
|
padding-left: 1rem;
|
||||||
|
}
|
||||||
|
.panel-heading {
|
||||||
|
padding: .5rem 1rem;
|
||||||
|
border-bottom: 1px solid transparent;
|
||||||
|
border-top-left-radius: .25em;
|
||||||
|
border-top-right-radius: .25em;
|
||||||
|
}
|
||||||
.modal-open .modal {
|
.modal-open .modal {
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
@@ -453,20 +494,6 @@ hr {
|
|||||||
border-radius: .25em;
|
border-radius: .25em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.table-bordered {
|
|
||||||
border: @border;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-bordered > thead > tr > th, .table-bordered > tbody > tr > th, .table-bordered > tfoot > tr > th, .table-bordered > thead > tr > td, .table-bordered > tbody > tr > td, .table-bordered > tfoot > tr > td {
|
|
||||||
border: @border;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table > thead > tr > th, .table > tbody > tr > th, .table > tfoot > tr > th, .table > thead > tr > td, .table > tbody > tr > td, .table > tfoot > tr > td {
|
|
||||||
padding: .5em;
|
|
||||||
vertical-align: top;
|
|
||||||
border-top: 1px solid @light-border-color;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-block {
|
.btn-block {
|
||||||
display: block;
|
display: block;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@@ -676,7 +703,7 @@ img.blog-cover-image, .blog-text img, .screenshot {
|
|||||||
.media {
|
.media {
|
||||||
display: flex;
|
display: flex;
|
||||||
padding: 1.5rem;
|
padding: 1.5rem;
|
||||||
background: #fafbfc;
|
background: @light-bg;
|
||||||
margin-bottom: 1.5rem;
|
margin-bottom: 1.5rem;
|
||||||
border-radius: .25em;
|
border-radius: .25em;
|
||||||
border: 1px solid lightgray;
|
border: 1px solid lightgray;
|
||||||
@@ -689,7 +716,15 @@ img.blog-cover-image, .blog-text img, .screenshot {
|
|||||||
.media-heading {
|
.media-heading {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
.media-object {
|
.with-border {
|
||||||
|
border: @border;
|
||||||
|
border-radius: 0.25em;
|
||||||
|
padding: 1rem;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
&:hover{
|
||||||
|
border-color: @text-light:;
|
||||||
|
background-color: @light-bg;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/* individual elements */
|
/* individual elements */
|
||||||
|
|
||||||
|
|||||||
@@ -17,12 +17,14 @@
|
|||||||
{%- block head -%}
|
{%- block head -%}
|
||||||
{% block meta_block %}{% endblock %}
|
{% block meta_block %}{% endblock %}
|
||||||
<link href="/assets/foundation/css/erpnext-org-theme.css" rel="stylesheet">
|
<link href="/assets/foundation/css/erpnext-org-theme.css" rel="stylesheet">
|
||||||
|
{% if path != '' %}
|
||||||
<link type="text/css" rel="stylesheet" href="/assets/frappe/css/hljs.css">
|
<link type="text/css" rel="stylesheet" href="/assets/frappe/css/hljs.css">
|
||||||
<link type="text/css" rel="stylesheet" href="/assets/frappe/css/font-awesome.css">
|
<link type="text/css" rel="stylesheet" href="/assets/frappe/css/font-awesome.css">
|
||||||
<link type="text/css" rel="stylesheet" href="/assets/frappe/css/octicons/octicons.css">
|
<link type="text/css" rel="stylesheet" href="/assets/frappe/css/octicons/octicons.css">
|
||||||
|
{% endif %}
|
||||||
{%- endblock -%}
|
{%- endblock -%}
|
||||||
{# loading required JS for login #}
|
{%- block style %}{%- endblock -%}
|
||||||
<script>
|
<script>
|
||||||
window.frappe = {};
|
window.frappe = {};
|
||||||
frappe.ready_events = [];
|
frappe.ready_events = [];
|
||||||
frappe.ready = function(fn) {
|
frappe.ready = function(fn) {
|
||||||
@@ -30,7 +32,6 @@
|
|||||||
}
|
}
|
||||||
window.dev_server = {{ dev_server }};
|
window.dev_server = {{ dev_server }};
|
||||||
</script>
|
</script>
|
||||||
{# loading required JS for login #}
|
|
||||||
</head>
|
</head>
|
||||||
<body data-path="{{ path }}">
|
<body data-path="{{ path }}">
|
||||||
<div class="wrapper">
|
<div class="wrapper">
|
||||||
|
|||||||
52
foundation/website/css/web_form.css
Normal file
52
foundation/website/css/web_form.css
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
.introduction {
|
||||||
|
border-bottom: 1px solid #e1e9f0;
|
||||||
|
padding: 15px;
|
||||||
|
padding-top: 0px;
|
||||||
|
margin-left: -15px;
|
||||||
|
margin-right: -15px;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group label {
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type='checkbox'] {
|
||||||
|
margin-top: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.checkbox label {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.web-form-page, .web-form-page .section {
|
||||||
|
padding: 20px 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.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;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slide-progress {
|
||||||
|
/*border-top: 1px solid #d1d8dd;*/
|
||||||
|
margin-top: -10px;
|
||||||
|
}
|
||||||
|
.slide-progress .fa-fw {
|
||||||
|
vertical-align: middle;
|
||||||
|
margin-right: 9px;
|
||||||
|
padding-left: 2px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.slide-progress .icon-circle-blank {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
.slide-progress .icon-circle {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
0
foundation/website/doctype/web_form/__init__.py
Normal file
0
foundation/website/doctype/web_form/__init__.py
Normal file
383
foundation/website/doctype/web_form/templates/web_form.html
Normal file
383
foundation/website/doctype/web_form/templates/web_form.html
Normal file
@@ -0,0 +1,383 @@
|
|||||||
|
{% extends "foundation/templates/web.html" %}
|
||||||
|
|
||||||
|
{% block title %}{{ _(title) }}{% endblock %}
|
||||||
|
|
||||||
|
{% block header %}
|
||||||
|
<h1>{{ _(title) }}</h1>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block breadcrumbs %}
|
||||||
|
{% if has_header and login_required %}
|
||||||
|
{% include "templates/includes/breadcrumbs.html" %}
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block header_actions %}
|
||||||
|
{% if not read_only and has_header %}
|
||||||
|
<div style="padding-bottom: 15px;">
|
||||||
|
{% if login_required -%}
|
||||||
|
<a href="{{ cancel_url or pathname }}" class="btn btn-default btn-sm">
|
||||||
|
{{ _("Cancel") }}</a>
|
||||||
|
{%- endif %}
|
||||||
|
{% if not is_list %}
|
||||||
|
<button type="submit" class="btn btn-primary btn-sm btn-form-submit">
|
||||||
|
{{ _("Save") }}</button>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% if is_list %}
|
||||||
|
<div style="padding-bottom: 15px;">
|
||||||
|
<a href="/{{ pathname }}{{ delimeter }}new=1{{ params_from_form_dict}}" class="btn btn-primary btn-new btn-sm">
|
||||||
|
{{ _("New") }}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{%- if allow_print and not is_list and not _login_required -%}
|
||||||
|
<div class='text-right'>
|
||||||
|
<a class='text-muted small' href='/printview?doctype={{ doc.doctype}}&name={{ doc.name }}
|
||||||
|
{%- if print_format -%}&format={{ print_format }}{%- endif -%}' target="_blank" rel="noopener noreferrer">
|
||||||
|
<i class='fa fa-print'></i> {{ _("Print") }}</a>
|
||||||
|
</div>
|
||||||
|
{%- endif -%}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block page_content %}
|
||||||
|
<div class="introduction">
|
||||||
|
{% if introduction_text %} hello
|
||||||
|
<p class="text-muted">{{ _(introduction_text) }}</p>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
<div class="form-message hide"></div>
|
||||||
|
{% if _login_required %}
|
||||||
|
<div class="login-required">
|
||||||
|
<div class="text-muted">
|
||||||
|
{{ _("Please sign-up or login to begin") }}
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
<a href="/login?redirect-to=/{{ pathname }}" class="btn btn-primary">
|
||||||
|
{{ _("Login") }}
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
{% elif is_list %}
|
||||||
|
{% include "templates/includes/list/list.html" %}
|
||||||
|
<script>{% include "templates/includes/list/list.js" %}</script>
|
||||||
|
{% else %}
|
||||||
|
<br>
|
||||||
|
|
||||||
|
{%- macro properties(field) %}
|
||||||
|
name="{{ field.fieldname }}" data-fieldname="{{ 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 "data-reqd=1" or "" }}
|
||||||
|
{{ (read_only or field.read_only) and "disabled" or "" }}
|
||||||
|
{% endmacro -%}
|
||||||
|
|
||||||
|
{%- macro value(field, _doc) -%}
|
||||||
|
{%- if _doc -%}
|
||||||
|
{%- set _value = _doc.get(field.fieldname) or frappe.form_dict.get(field.fieldname) -%}
|
||||||
|
{%- else -%}
|
||||||
|
{%- set _value = frappe.form_dict.get(field.fieldname) or field.default -%}
|
||||||
|
{%- endif -%}
|
||||||
|
{{ "" if _value==None else _value }}
|
||||||
|
{%- endmacro -%}
|
||||||
|
|
||||||
|
{%- macro help(field) -%}
|
||||||
|
{% if field.description -%}
|
||||||
|
<span class="help-block small text-muted">{{ _(field.description) }}</span>
|
||||||
|
{%- endif -%}
|
||||||
|
{%- endmacro %}
|
||||||
|
|
||||||
|
{% macro label(field) %}
|
||||||
|
<label for="{{ field.fieldname }}" class="control-label text-muted small">
|
||||||
|
{{ _(field.label) }}</label>
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
|
{% macro render_field(field, _doc=None, with_label=True) %}
|
||||||
|
{% if field.hidden %}
|
||||||
|
<input type="hidden" data-doctype="{{ field.parent }}"
|
||||||
|
name="{{ field.fieldname }}" value="{{ value(field, _doc) }}">
|
||||||
|
{% elif field.fieldtype == "HTML" %}
|
||||||
|
<div class="form-group" data-label="{{ field.label }}">
|
||||||
|
{% if field.options %}{{ field.options }}{% endif %}
|
||||||
|
</div>
|
||||||
|
{% elif field.fieldtype in ("Data", "Date", "Datetime", "Int", "Float") %}
|
||||||
|
<div class="form-group{% if field.reqd %} has-error{% endif %}">
|
||||||
|
{% if with_label %}{{ label(field) }}{% endif %}
|
||||||
|
<input type={{ "number" if field.fieldtype in ("Int", "Float") else "text" }}
|
||||||
|
class="form-control" {{ properties(field) }}
|
||||||
|
value="{{ value(field, _doc) }}"
|
||||||
|
{%- if field.fieldtype=="Int" %} pattern="[0-9]*"{% endif %}
|
||||||
|
{%- if field.max_length %} maxlength={{ field.max_length }}{% endif %}>
|
||||||
|
{{ help(field) }}
|
||||||
|
</div>
|
||||||
|
{% elif field.fieldtype=="Link" %}
|
||||||
|
<div class="form-group{% if field.reqd %} has-error{% endif %}">
|
||||||
|
{% 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 field.reqd %} has-error{% endif %}">
|
||||||
|
{% 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, _doc)==option else '' }}>
|
||||||
|
{{ _(option) }}</option>
|
||||||
|
{%- endfor %}
|
||||||
|
</select>
|
||||||
|
{{ help(field) }}
|
||||||
|
</div>
|
||||||
|
{% elif field.fieldtype in ("Text", "Small Text") %}
|
||||||
|
<div class="form-group{% if field.reqd %} has-error{% endif %}">
|
||||||
|
{% if with_label %}{{ label(field) }}{% endif %}
|
||||||
|
{{ help(field) }}
|
||||||
|
<textarea class="form-control" style="height: {% if field.fieldtype=="Small Text" %}150px{% else %}300px;{% endif %}"
|
||||||
|
{{ properties(field) }}>{{ value(field, _doc) }}</textarea>
|
||||||
|
</div>
|
||||||
|
{% elif field.fieldtype == "Text Editor" %}
|
||||||
|
<div class="form-group{% if field.reqd %} has-error{% endif %}">
|
||||||
|
{% if with_label %}{{ label(field) }}{% endif %}
|
||||||
|
{{ help(field) }}
|
||||||
|
<div {{ properties(field) }}>{{ value(field, _doc) }}</div>
|
||||||
|
</div>
|
||||||
|
{% elif field.fieldtype=="Attach" %}
|
||||||
|
<div class="form-group">
|
||||||
|
{% 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) }}
|
||||||
|
</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, _doc) and 'hide' or '' }} attach-input-wrap">
|
||||||
|
<input type="file" style="margin-top: 7px;"
|
||||||
|
{{ properties(field) }}
|
||||||
|
{%- if value(field, _doc) -%} data-value="{{ value(field, _doc) }}"{%- endif -%}>
|
||||||
|
<p class='text-muted small' style='margin-bottom: 20px;'>
|
||||||
|
{{ _("Max attachment size is {0}MB").format(max_attachment_size) }}
|
||||||
|
</p>
|
||||||
|
</p>
|
||||||
|
{{ help(field) }}
|
||||||
|
</div>
|
||||||
|
{% elif field.fieldtype=="Check" %}
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="checkbox">
|
||||||
|
{% if with_label %}
|
||||||
|
<label class='text-muted'>
|
||||||
|
<input type="checkbox" id="{{ field.fieldname }}"
|
||||||
|
{{ properties(field) }}
|
||||||
|
name="{{ field.fieldname }}" data-doctype="{{ field.parent }}"
|
||||||
|
{{ _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 or "" }}" 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: {{ (df.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='fa fa-remove'></i></button>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% 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'>
|
||||||
|
<thead>
|
||||||
|
{{ render_row(field) }}
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{{ render_row(field, {}, True) }}
|
||||||
|
{% if doc and doc.get(field.fieldname) %}
|
||||||
|
{% for d in doc.get(field.fieldname) %}
|
||||||
|
{{ render_row(field, d) }}
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<p><button class='btn btn-default btn-sm btn-add-row'
|
||||||
|
data-fieldname='{{ field.fieldname }}'>{{ _("Add Row") }}</button></p>
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
|
<!-- pagination -->
|
||||||
|
{% if not frappe.form_dict.new and layout|len > 1 %}
|
||||||
|
<div class="text-center slide-progress text-extra-muted">
|
||||||
|
{% for page in layout %}
|
||||||
|
<i data-idx="{{ loop.index }}" data-toggle="tooltip" data-placement="top"
|
||||||
|
title="{{ _(page.label) or _("Page {0}").format(loop.index) }}" class="fa-fw
|
||||||
|
{% if loop.index==1 %}fa fa-circle{% else %}fa fa-circle-o{% endif %}"></i>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<form role="form"
|
||||||
|
data-web-form="{{ name }}" data-owner="{{ doc.owner }}">
|
||||||
|
{% if frappe.form_dict.name and web_page_link_text %}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<p class="text-muted">
|
||||||
|
<a class="btn btn-default btn-sm" href="{{ doc.route }}" target="_blank" rel="noopener noreferrer">
|
||||||
|
{{ web_page_link_text }}</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% for page in layout %}
|
||||||
|
{% set last_page = True if loop.index == layout|len else False %}
|
||||||
|
<div class="web-form-page{% if loop.index > 1 %} hidden{% endif %}"
|
||||||
|
data-idx="{{ loop.index }}"
|
||||||
|
data-label="{{ page.label or _("Page {0}").format(loop.index) }}">
|
||||||
|
{% if page.label %}
|
||||||
|
<h2 class='text-center'>{{ _(page.label) }}</h2>
|
||||||
|
{% endif %}
|
||||||
|
{% if page.description %}
|
||||||
|
<p class='text-center text-muted small'>{{ _(page.description) }}</p>
|
||||||
|
<br>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% for section in page.sections %}
|
||||||
|
<div class="section">
|
||||||
|
{% if section.label %}
|
||||||
|
<h5 class='uppercase'>{{ _(section.label) }}</h5>
|
||||||
|
<span class="help-block small text-muted">{{ _(section.description) }}</span>
|
||||||
|
{% 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 %}
|
||||||
|
{% if last_page and accept_payment %}
|
||||||
|
<div class="well payment-details">
|
||||||
|
{% if not doc.paid %}
|
||||||
|
{% if payment_button_help %}
|
||||||
|
<div class='text-muted' style='padding-bottom: 15px;'>
|
||||||
|
{{ payment_button_help }}</div>
|
||||||
|
{% endif %}
|
||||||
|
<a class="btn btn-primary btn-payment">
|
||||||
|
{{ payment_button_label or "Pay"}}</a>
|
||||||
|
{% else %}
|
||||||
|
<div>{{ _("Payment Complete") }}</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
<!-- page footer buttons -->
|
||||||
|
<div>
|
||||||
|
{% if layout|len > 1 %}
|
||||||
|
<p class='text-muted small text-center'>
|
||||||
|
{{ _("Page {0} of {1}").format(loop.index, layout|len) }}</p>
|
||||||
|
{% endif %}
|
||||||
|
<br>
|
||||||
|
<p class='text-right'>
|
||||||
|
{%- if loop.index > 1 -%}
|
||||||
|
<button class='btn btn-sm btn-default btn-change-section'
|
||||||
|
data-idx="{{ loop.index - 1 }}">
|
||||||
|
{{ _("Previous") }}</button>
|
||||||
|
{%- endif -%}
|
||||||
|
<!-- save/next button -->
|
||||||
|
{% if (loop.index == layout|len or frappe.form_dict.new) %}
|
||||||
|
{% if not read_only %}
|
||||||
|
<button type="submit" class="btn btn-primary btn-sm btn-form-submit">
|
||||||
|
{{ _("Save") }}</button>
|
||||||
|
{% endif %}
|
||||||
|
{% elif layout|len > 1 %}
|
||||||
|
<button class="btn btn-primary btn-sm btn-change-section"
|
||||||
|
data-idx="{{ loop.index + 1 }}">
|
||||||
|
{{ _("Next") }}</button>
|
||||||
|
{% endif %}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
</form>
|
||||||
|
|
||||||
|
{% if allow_comments and not frappe.form_dict.new -%}
|
||||||
|
<div class="comments">
|
||||||
|
<br><br>
|
||||||
|
<h3>{{ _("Comments") }}</h3>
|
||||||
|
{% include 'templates/includes/comments/comments.html' %}
|
||||||
|
</div>
|
||||||
|
{%- endif %}
|
||||||
|
{% endif %}
|
||||||
|
<div class="padding"></div>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block script %}
|
||||||
|
|
||||||
|
<script>
|
||||||
|
window.web_form_settings = {
|
||||||
|
allow_incomplete: {{ allow_incomplete or 0 }},
|
||||||
|
success_link: '<p>{{ success_message or _("Your information has been submitted") }}</p><p><a href="{{ success_url or "/" }}" class="btn btn-sm btn-default">{{ _("Continue") }}</a></p>',
|
||||||
|
datepicker_format: "{{ frappe.date_format }}",
|
||||||
|
web_form_doctype: "{{ doc_type }}",
|
||||||
|
web_form_name: "{{ name }}",
|
||||||
|
is_new: {{ 1 if frappe.form_dict.new else 0 }},
|
||||||
|
is_read_only: {{ 1 if read_only else 0 }},
|
||||||
|
doc_name: "{{ frappe.form_dict.name or "" }}",
|
||||||
|
login_required: {{ 1 if login_required else 0 }},
|
||||||
|
max_attachment_size:{{ max_attachment_size }},
|
||||||
|
moment_date_format: "{{ frappe.date_format.upper() }}"
|
||||||
|
}
|
||||||
|
{% if row_template %}web_form_settings.web_form_row_template = "{{ row_template }}";{% endif %}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/javascript" src="/assets/js/web_form.min.js"></script>
|
||||||
|
<script>
|
||||||
|
{% if script is defined %}
|
||||||
|
{{ script }}
|
||||||
|
{% endif %}
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block style %}
|
||||||
|
<link type="text/css" rel="stylesheet" href="/assets/css/web_form.css">
|
||||||
|
<link href="/assets/foundation/css/bootstrap-for-webform.css" rel="stylesheet">
|
||||||
|
<style>
|
||||||
|
{% if style is defined %}{{ style }}{% endif %}
|
||||||
|
</style>
|
||||||
|
{% endblock %}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
<div>
|
||||||
|
<a href={{ route }}>{{ title }}</a>
|
||||||
|
</div>
|
||||||
|
<!-- this is a sample default list template -->
|
||||||
48
foundation/website/doctype/web_form/test_records.json
Normal file
48
foundation/website/doctype/web_form/test_records.json
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
[{
|
||||||
|
"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
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}]
|
||||||
68
foundation/website/doctype/web_form/test_web_form.py
Normal file
68
foundation/website/doctype/web_form/test_web_form.py
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||||
|
# See license.txt
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import frappe
|
||||||
|
import unittest, json
|
||||||
|
|
||||||
|
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):
|
||||||
|
def setUp(self):
|
||||||
|
frappe.conf.disable_website_cache = True
|
||||||
|
frappe.local.path = None
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
frappe.conf.disable_website_cache = False
|
||||||
|
frappe.local.path = None
|
||||||
|
|
||||||
|
def test_basic(self):
|
||||||
|
frappe.set_user("Guest")
|
||||||
|
html = build_page("manage-events")
|
||||||
|
self.assertTrue('<div class="login-required">' in html)
|
||||||
|
|
||||||
|
def test_logged_in(self):
|
||||||
|
frappe.set_user("Administrator")
|
||||||
|
html = build_page("manage-events")
|
||||||
|
self.assertFalse('<div class="login-required">' 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")
|
||||||
|
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"})
|
||||||
|
self.assertTrue(self.event_name)
|
||||||
|
|
||||||
|
def test_edit(self):
|
||||||
|
self.test_accept()
|
||||||
|
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"), doc.get('description'))
|
||||||
|
|
||||||
|
accept(web_form='manage-events', data=json.dumps(doc))
|
||||||
|
|
||||||
|
self.assertEquals(frappe.db.get_value("Event",
|
||||||
|
self.event_name, "description"), doc.get('description'))
|
||||||
80
foundation/website/doctype/web_form/web_form.js
Normal file
80
foundation/website/doctype/web_form/web_form.js
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
frappe.web_form = {
|
||||||
|
set_fieldname_select: function(frm) {
|
||||||
|
var me = this,
|
||||||
|
doc = frm.doc;
|
||||||
|
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) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
var currency_fields = $.map(frappe.get_doc("DocType", frm.doc.doc_type).fields, function(d) {
|
||||||
|
if (d.fieldtype === 'Currency' || d.fieldtype === 'Float') {
|
||||||
|
return { label: d.label, value: d.fieldname }
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
frappe.meta.get_docfield("Web Form Field", "fieldname", frm.doc.name).options = [""].concat(fields);
|
||||||
|
frappe.meta.get_docfield("Web Form", "amount_field", frm.doc.name).options = [""].concat(currency_fields);
|
||||||
|
frm.refresh_field("amount_field");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
frappe.ui.form.on("Web Form", {
|
||||||
|
refresh: function(frm) {
|
||||||
|
// show is-standard only if developer mode
|
||||||
|
frm.get_field("is_standard").toggle(frappe.boot.developer_mode);
|
||||||
|
|
||||||
|
frappe.web_form.set_fieldname_select(frm);
|
||||||
|
|
||||||
|
if (frm.doc.is_standard && !frappe.boot.developer_mode) {
|
||||||
|
frm.set_read_only();
|
||||||
|
frm.disable_save();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
title: function(frm) {
|
||||||
|
if (frm.doc.__islocal) {
|
||||||
|
var page_name = frm.doc.title.toLowerCase().replace(/ /g, "-");
|
||||||
|
frm.set_value("route", page_name);
|
||||||
|
frm.set_value("success_url", "/" + page_name);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
doc_type: function(frm) {
|
||||||
|
frappe.web_form.set_fieldname_select(frm);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
frappe.ui.form.on("Web Form Field", {
|
||||||
|
fieldtype: function(frm, doctype, name) {
|
||||||
|
var doc = frappe.get_doc(doctype, name);
|
||||||
|
if (['Section Break', 'Column Break', 'Page Break'].includes(doc.fieldtype)) {
|
||||||
|
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"];
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
1217
foundation/website/doctype/web_form/web_form.json
Normal file
1217
foundation/website/doctype/web_form/web_form.json
Normal file
File diff suppressed because it is too large
Load Diff
485
foundation/website/doctype/web_form/web_form.py
Normal file
485
foundation/website/doctype/web_form/web_form.py
Normal file
@@ -0,0 +1,485 @@
|
|||||||
|
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
|
# For license information, please see license.txt
|
||||||
|
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
import frappe, json, os
|
||||||
|
from frappe.website.website_generator import WebsiteGenerator
|
||||||
|
from frappe import _, scrub
|
||||||
|
from frappe.utils import cstr
|
||||||
|
from frappe.utils.file_manager import save_file, remove_file_by_url
|
||||||
|
from frappe.website.utils import get_comment_list
|
||||||
|
from frappe.custom.doctype.customize_form.customize_form import docfield_properties
|
||||||
|
from frappe.utils.file_manager import get_max_file_size
|
||||||
|
from frappe.modules.utils import export_module_json, get_doc_module
|
||||||
|
from six.moves.urllib.parse import urlencode
|
||||||
|
from frappe.integrations.utils import get_payment_gateway_controller
|
||||||
|
from six import iteritems
|
||||||
|
|
||||||
|
|
||||||
|
class WebForm(WebsiteGenerator):
|
||||||
|
website = frappe._dict(
|
||||||
|
no_cache = 1
|
||||||
|
)
|
||||||
|
|
||||||
|
def onload(self):
|
||||||
|
super(WebForm, self).onload()
|
||||||
|
if self.is_standard and not frappe.conf.developer_mode:
|
||||||
|
self.use_meta_fields()
|
||||||
|
|
||||||
|
def validate(self):
|
||||||
|
super(WebForm, self).validate()
|
||||||
|
|
||||||
|
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"))
|
||||||
|
|
||||||
|
if not frappe.flags.in_import:
|
||||||
|
self.validate_fields()
|
||||||
|
|
||||||
|
if self.accept_payment:
|
||||||
|
self.validate_payment_amount()
|
||||||
|
|
||||||
|
def validate_fields(self):
|
||||||
|
'''Validate all fields are present'''
|
||||||
|
from frappe.model import no_value_fields
|
||||||
|
missing = []
|
||||||
|
meta = frappe.get_meta(self.doc_type)
|
||||||
|
for df in self.web_form_fields:
|
||||||
|
if df.fieldname and (df.fieldtype not in no_value_fields and not meta.has_field(df.fieldname)):
|
||||||
|
missing.append(df.fieldname)
|
||||||
|
|
||||||
|
if missing:
|
||||||
|
frappe.throw(_('Following fields are missing:') + '<br>' + '<br>'.join(missing))
|
||||||
|
|
||||||
|
def validate_payment_amount(self):
|
||||||
|
if self.amount_based_on_field and not self.amount_field:
|
||||||
|
frappe.throw(_("Please select a Amount Field."))
|
||||||
|
elif not self.amount_based_on_field and not self.amount > 0:
|
||||||
|
frappe.throw(_("Amount must be greater than 0."))
|
||||||
|
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
def use_meta_fields(self):
|
||||||
|
'''Override default properties for standard web forms'''
|
||||||
|
meta = frappe.get_meta(self.doc_type)
|
||||||
|
|
||||||
|
for df in self.web_form_fields:
|
||||||
|
meta_df = meta.get_field(df.fieldname)
|
||||||
|
|
||||||
|
if not meta_df:
|
||||||
|
continue
|
||||||
|
|
||||||
|
for prop in docfield_properties:
|
||||||
|
if df.fieldtype==meta_df.fieldtype and prop not in ("idx",
|
||||||
|
"reqd", "default", "description", "default", "options",
|
||||||
|
"hidden", "read_only", "label"):
|
||||||
|
df.set(prop, meta_df.get(prop))
|
||||||
|
|
||||||
|
|
||||||
|
# TODO translate options of Select fields like Country
|
||||||
|
|
||||||
|
# export
|
||||||
|
def on_update(self):
|
||||||
|
"""
|
||||||
|
Writes the .txt for this page and if write_content is checked,
|
||||||
|
it will write out a .html file
|
||||||
|
"""
|
||||||
|
path = export_module_json(self, self.is_standard, self.module)
|
||||||
|
|
||||||
|
if path:
|
||||||
|
# js
|
||||||
|
if not os.path.exists(path + '.js'):
|
||||||
|
with open(path + '.js', 'w') as f:
|
||||||
|
f.write("""frappe.ready(function() {
|
||||||
|
// bind events here
|
||||||
|
})""")
|
||||||
|
|
||||||
|
# py
|
||||||
|
if not os.path.exists(path + '.py'):
|
||||||
|
with open(path + '.py', 'w') as f:
|
||||||
|
f.write("""from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import frappe
|
||||||
|
|
||||||
|
def get_context(context):
|
||||||
|
# do your magic here
|
||||||
|
pass
|
||||||
|
""")
|
||||||
|
|
||||||
|
def get_context(self, context):
|
||||||
|
'''Build context to render the `web_form.html` template'''
|
||||||
|
self.set_web_form_module()
|
||||||
|
|
||||||
|
context._login_required = False
|
||||||
|
if self.login_required and frappe.session.user == "Guest":
|
||||||
|
context._login_required = True
|
||||||
|
|
||||||
|
doc, delimeter = make_route_string(frappe.form_dict)
|
||||||
|
context.doc = doc
|
||||||
|
context.delimeter = delimeter
|
||||||
|
|
||||||
|
# check permissions
|
||||||
|
if frappe.session.user == "Guest" and frappe.form_dict.name:
|
||||||
|
frappe.throw(_("You need to be logged in to access this {0}.").format(self.doc_type), frappe.PermissionError)
|
||||||
|
|
||||||
|
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()
|
||||||
|
|
||||||
|
if self.is_standard:
|
||||||
|
self.use_meta_fields()
|
||||||
|
|
||||||
|
if not context._login_required:
|
||||||
|
if self.allow_edit:
|
||||||
|
if self.allow_multiple:
|
||||||
|
if not frappe.form_dict.name and not frappe.form_dict.new:
|
||||||
|
self.build_as_list(context)
|
||||||
|
else:
|
||||||
|
if frappe.session.user != 'Guest' and not frappe.form_dict.name:
|
||||||
|
frappe.form_dict.name = frappe.db.get_value(self.doc_type, {"owner": frappe.session.user}, "name")
|
||||||
|
|
||||||
|
if not frappe.form_dict.name:
|
||||||
|
# only a single doc allowed and no existing doc, hence new
|
||||||
|
frappe.form_dict.new = 1
|
||||||
|
|
||||||
|
# always render new form if login is not required or doesn't allow editing existing ones
|
||||||
|
if not self.login_required or not self.allow_edit:
|
||||||
|
frappe.form_dict.new = 1
|
||||||
|
|
||||||
|
self.load_document(context)
|
||||||
|
context.parents = self.get_parents(context)
|
||||||
|
|
||||||
|
if self.breadcrumbs:
|
||||||
|
context.parents = frappe.safe_eval(self.breadcrumbs, { "_": _ })
|
||||||
|
|
||||||
|
context.has_header = ((frappe.form_dict.name or frappe.form_dict.new)
|
||||||
|
and (frappe.session.user!="Guest" or not self.login_required))
|
||||||
|
|
||||||
|
if context.success_message:
|
||||||
|
context.success_message = frappe.db.escape(context.success_message.replace("\n",
|
||||||
|
"<br>"))
|
||||||
|
|
||||||
|
self.add_custom_context_and_script(context)
|
||||||
|
if not context.max_attachment_size:
|
||||||
|
context.max_attachment_size = get_max_file_size() / 1024 / 1024
|
||||||
|
|
||||||
|
def load_document(self, context):
|
||||||
|
'''Load document `doc` and `layout` properties for template'''
|
||||||
|
if frappe.form_dict.name or frappe.form_dict.new:
|
||||||
|
context.layout = self.get_layout()
|
||||||
|
context.parents = [{"route": self.route, "label": _(self.title) }]
|
||||||
|
|
||||||
|
if frappe.form_dict.name:
|
||||||
|
context.doc = frappe.get_doc(self.doc_type, frappe.form_dict.name)
|
||||||
|
context.title = context.doc.get(context.doc.meta.get_title_field())
|
||||||
|
context.doc.add_seen()
|
||||||
|
|
||||||
|
context.reference_doctype = context.doc.doctype
|
||||||
|
context.reference_name = context.doc.name
|
||||||
|
|
||||||
|
if self.allow_comments:
|
||||||
|
context.comment_list = get_comment_list(context.doc.doctype,
|
||||||
|
context.doc.name)
|
||||||
|
|
||||||
|
def build_as_list(self, context):
|
||||||
|
'''Web form is a list, show render as list.html'''
|
||||||
|
from frappe.www.list import get_context as get_list_context
|
||||||
|
|
||||||
|
# set some flags to make list.py/list.html happy
|
||||||
|
frappe.form_dict.web_form_name = self.name
|
||||||
|
frappe.form_dict.doctype = self.doc_type
|
||||||
|
frappe.flags.web_form = self
|
||||||
|
|
||||||
|
self.update_params_from_form_dict(context)
|
||||||
|
self.update_list_context(context)
|
||||||
|
get_list_context(context)
|
||||||
|
context.is_list = True
|
||||||
|
|
||||||
|
def update_params_from_form_dict(self, context):
|
||||||
|
'''Copy params from list view to new view'''
|
||||||
|
context.params_from_form_dict = ''
|
||||||
|
|
||||||
|
params = {}
|
||||||
|
for key, value in iteritems(frappe.form_dict):
|
||||||
|
if frappe.get_meta(self.doc_type).get_field(key):
|
||||||
|
params[key] = value
|
||||||
|
|
||||||
|
if params:
|
||||||
|
context.params_from_form_dict = '&' + urlencode(params)
|
||||||
|
|
||||||
|
|
||||||
|
def update_list_context(self, context):
|
||||||
|
'''update list context for stanard modules'''
|
||||||
|
if hasattr(self, 'web_form_module') and hasattr(self.web_form_module, 'get_list_context'):
|
||||||
|
self.web_form_module.get_list_context(context)
|
||||||
|
|
||||||
|
def get_payment_gateway_url(self, doc):
|
||||||
|
if self.accept_payment:
|
||||||
|
controller = get_payment_gateway_controller(self.payment_gateway)
|
||||||
|
|
||||||
|
title = "Payment for {0} {1}".format(doc.doctype, doc.name)
|
||||||
|
amount = self.amount
|
||||||
|
if self.amount_based_on_field:
|
||||||
|
amount = doc.get(self.amount_field)
|
||||||
|
payment_details = {
|
||||||
|
"amount": amount,
|
||||||
|
"title": title,
|
||||||
|
"description": title,
|
||||||
|
"reference_doctype": doc.doctype,
|
||||||
|
"reference_docname": doc.name,
|
||||||
|
"payer_email": frappe.session.user,
|
||||||
|
"payer_name": frappe.utils.get_fullname(frappe.session.user),
|
||||||
|
"order_id": doc.name,
|
||||||
|
"currency": self.currency,
|
||||||
|
"redirect_to": frappe.utils.get_url(self.route)
|
||||||
|
}
|
||||||
|
|
||||||
|
# Redirect the user to this url
|
||||||
|
return controller.get_payment_url(**payment_details)
|
||||||
|
|
||||||
|
def add_custom_context_and_script(self, context):
|
||||||
|
'''Update context from module if standard and append script'''
|
||||||
|
if self.web_form_module:
|
||||||
|
new_context = self.web_form_module.get_context(context)
|
||||||
|
|
||||||
|
if new_context:
|
||||||
|
context.update(new_context)
|
||||||
|
|
||||||
|
js_path = os.path.join(os.path.dirname(self.web_form_module.__file__), scrub(self.name) + '.js')
|
||||||
|
if os.path.exists(js_path):
|
||||||
|
context.script = frappe.render_template(open(js_path, 'r').read().decode('utf-8'), context)
|
||||||
|
|
||||||
|
css_path = os.path.join(os.path.dirname(self.web_form_module.__file__), scrub(self.name) + '.css')
|
||||||
|
if os.path.exists(css_path):
|
||||||
|
context.style = open(css_path, 'r').read()
|
||||||
|
|
||||||
|
def get_layout(self):
|
||||||
|
layout = []
|
||||||
|
def add_page(df=None):
|
||||||
|
new_page = {'sections': []}
|
||||||
|
layout.append(new_page)
|
||||||
|
if df and df.fieldtype=='Page Break':
|
||||||
|
new_page.update(df.as_dict())
|
||||||
|
|
||||||
|
return new_page
|
||||||
|
|
||||||
|
def add_section(df=None):
|
||||||
|
new_section = {'columns': []}
|
||||||
|
layout[-1]['sections'].append(new_section)
|
||||||
|
if df and df.fieldtype=='Section Break':
|
||||||
|
new_section.update(df.as_dict())
|
||||||
|
|
||||||
|
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:
|
||||||
|
|
||||||
|
# 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 column==None:
|
||||||
|
column = add_column()
|
||||||
|
column.append(df)
|
||||||
|
|
||||||
|
return layout
|
||||||
|
|
||||||
|
def get_parents(self, context):
|
||||||
|
parents = None
|
||||||
|
|
||||||
|
if context.is_list and not context.parents:
|
||||||
|
parents = [{"title": _("My Account"), "name": "me"}]
|
||||||
|
elif context.parents:
|
||||||
|
parents = context.parents
|
||||||
|
|
||||||
|
return parents
|
||||||
|
|
||||||
|
def set_web_form_module(self):
|
||||||
|
'''Get custom web form module if exists'''
|
||||||
|
if self.is_standard:
|
||||||
|
self.web_form_module = get_doc_module(self.module, self.doctype, self.name)
|
||||||
|
else:
|
||||||
|
self.web_form_module = None
|
||||||
|
|
||||||
|
def validate_mandatory(self, doc):
|
||||||
|
'''Validate mandatory web form fields'''
|
||||||
|
missing = []
|
||||||
|
for f in self.web_form_fields:
|
||||||
|
if f.reqd and doc.get(f.fieldname) in (None, [], ''):
|
||||||
|
missing.append(f)
|
||||||
|
|
||||||
|
if missing:
|
||||||
|
frappe.throw(_('Mandatory Information missing:') + '<br><br>'
|
||||||
|
+ '<br>'.join(['{0} ({1})'.format(d.label, d.fieldtype) for d in missing]))
|
||||||
|
|
||||||
|
|
||||||
|
@frappe.whitelist(allow_guest=True)
|
||||||
|
def accept(web_form, data, for_payment=False):
|
||||||
|
'''Save the web form'''
|
||||||
|
data = frappe._dict(json.loads(data))
|
||||||
|
files = []
|
||||||
|
files_to_delete = []
|
||||||
|
|
||||||
|
web_form = frappe.get_doc("Web Form", web_form)
|
||||||
|
if data.doctype != web_form.doc_type:
|
||||||
|
frappe.throw(_("Invalid Request"))
|
||||||
|
|
||||||
|
elif data.name and not web_form.allow_edit:
|
||||||
|
frappe.throw(_("You are not allowed to update this Web Form Document"))
|
||||||
|
|
||||||
|
frappe.flags.in_web_form = True
|
||||||
|
|
||||||
|
if data.name:
|
||||||
|
# update
|
||||||
|
doc = frappe.get_doc(data.doctype, data.name)
|
||||||
|
else:
|
||||||
|
# insert
|
||||||
|
doc = frappe.new_doc(data.doctype)
|
||||||
|
|
||||||
|
# set values
|
||||||
|
for fieldname, value in iteritems(data):
|
||||||
|
if value and isinstance(value, dict):
|
||||||
|
try:
|
||||||
|
if "__file_attachment" in value:
|
||||||
|
files.append((fieldname, value))
|
||||||
|
continue
|
||||||
|
if '__no_attachment' in value:
|
||||||
|
files_to_delete.append(doc.get(fieldname))
|
||||||
|
value = ''
|
||||||
|
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
doc.set(fieldname, value)
|
||||||
|
|
||||||
|
if for_payment:
|
||||||
|
web_form.validate_mandatory(doc)
|
||||||
|
doc.run_method('validate_payment')
|
||||||
|
|
||||||
|
if doc.name:
|
||||||
|
if has_web_form_permission(doc.doctype, doc.name, "write"):
|
||||||
|
doc.save(ignore_permissions=True)
|
||||||
|
else:
|
||||||
|
# only if permissions are present
|
||||||
|
doc.save()
|
||||||
|
|
||||||
|
else:
|
||||||
|
# insert
|
||||||
|
if web_form.login_required and frappe.session.user=="Guest":
|
||||||
|
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 attached 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()
|
||||||
|
|
||||||
|
if files_to_delete:
|
||||||
|
for f in files_to_delete:
|
||||||
|
if f:
|
||||||
|
remove_file_by_url(f, doc.doctype, doc.name)
|
||||||
|
|
||||||
|
frappe.flags.web_form_doc = doc
|
||||||
|
|
||||||
|
if for_payment:
|
||||||
|
return web_form.get_payment_gateway_url(doc)
|
||||||
|
else:
|
||||||
|
return doc.name
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def delete(web_form, name):
|
||||||
|
web_form = frappe.get_doc("Web Form", web_form)
|
||||||
|
|
||||||
|
owner = frappe.db.get_value(web_form.doc_type, name, "owner")
|
||||||
|
if frappe.session.user == owner and web_form.allow_delete:
|
||||||
|
frappe.delete_doc(web_form.doc_type, name, ignore_permissions=True)
|
||||||
|
else:
|
||||||
|
raise frappe.PermissionError("Not Allowed")
|
||||||
|
|
||||||
|
def has_web_form_permission(doctype, name, ptype='read'):
|
||||||
|
if frappe.session.user=="Guest":
|
||||||
|
return False
|
||||||
|
|
||||||
|
# owner matches
|
||||||
|
elif frappe.db.get_value(doctype, name, "owner")==frappe.session.user:
|
||||||
|
return True
|
||||||
|
|
||||||
|
elif frappe.has_website_permission(name, ptype=ptype, doctype=doctype):
|
||||||
|
return True
|
||||||
|
|
||||||
|
elif check_webform_perm(doctype, name):
|
||||||
|
return True
|
||||||
|
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def check_webform_perm(doctype, name):
|
||||||
|
doc = frappe.get_doc(doctype, name)
|
||||||
|
if hasattr(doc, "has_webform_permission"):
|
||||||
|
if doc.has_webform_permission():
|
||||||
|
return True
|
||||||
|
|
||||||
|
def get_web_form_list(doctype, txt, filters, limit_start, limit_page_length=20, order_by=None):
|
||||||
|
from frappe.www.list import get_list
|
||||||
|
if not filters:
|
||||||
|
filters = {}
|
||||||
|
|
||||||
|
filters["owner"] = frappe.session.user
|
||||||
|
|
||||||
|
return get_list(doctype, txt, filters, limit_start, limit_page_length, order_by=order_by,
|
||||||
|
ignore_permissions=True)
|
||||||
|
|
||||||
|
def make_route_string(parameters):
|
||||||
|
route_string = ""
|
||||||
|
delimeter = '?'
|
||||||
|
if isinstance(parameters, dict):
|
||||||
|
for key in parameters:
|
||||||
|
if key != "web_form_name":
|
||||||
|
route_string += route_string + delimeter + key + "=" + cstr(parameters[key])
|
||||||
|
delimeter = '&'
|
||||||
|
return (route_string, delimeter)
|
||||||
432
foundation/website/doctype/web_form_field/web_form_field.json
Normal file
432
foundation/website/doctype/web_form_field/web_form_field.json
Normal file
@@ -0,0 +1,432 @@
|
|||||||
|
{
|
||||||
|
"allow_copy": 0,
|
||||||
|
"allow_import": 0,
|
||||||
|
"allow_rename": 0,
|
||||||
|
"beta": 0,
|
||||||
|
"creation": "2014-09-01 14:14:14.292173",
|
||||||
|
"custom": 0,
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "DocType",
|
||||||
|
"document_type": "",
|
||||||
|
"editable_grid": 1,
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "fieldname",
|
||||||
|
"fieldtype": "Select",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 1,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Fieldname",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 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": "fieldtype",
|
||||||
|
"fieldtype": "Select",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 1,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Fieldtype",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"options": "Attach\nCheck\nData\nDate\nDatetime\nFloat\nHTML\nInt\nLink\nSelect\nSmall Text\nText\nText Editor\nTable\nSection Break\nColumn Break\nPage Break",
|
||||||
|
"permlevel": 0,
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 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": "label",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 1,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Label",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 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": "reqd",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Mandatory",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 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": "read_only",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Read Only",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 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": "hidden",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Hidden",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 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": "column_break_4",
|
||||||
|
"fieldtype": "Column Break",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 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": "options",
|
||||||
|
"fieldtype": "Text",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 1,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Options",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 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": "max_length",
|
||||||
|
"fieldtype": "Int",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Max Length",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 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,
|
||||||
|
"depends_on": "eval:doc.fieldtype=='Int'",
|
||||||
|
"fieldname": "max_value",
|
||||||
|
"fieldtype": "Int",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Max Value",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 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": "section_break_6",
|
||||||
|
"fieldtype": "Section Break",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 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": "description",
|
||||||
|
"fieldtype": "Text",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Description",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 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": "column_break_8",
|
||||||
|
"fieldtype": "Column Break",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 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": "default",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Default",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"hide_heading": 0,
|
||||||
|
"hide_toolbar": 0,
|
||||||
|
"idx": 0,
|
||||||
|
"image_view": 0,
|
||||||
|
"in_create": 0,
|
||||||
|
"in_dialog": 0,
|
||||||
|
"is_submittable": 0,
|
||||||
|
"issingle": 0,
|
||||||
|
"istable": 1,
|
||||||
|
"max_attachments": 0,
|
||||||
|
"modified": "2017-02-27 15:55:00.850515",
|
||||||
|
"modified_by": "Administrator",
|
||||||
|
"module": "Website",
|
||||||
|
"name": "Web Form Field",
|
||||||
|
"name_case": "",
|
||||||
|
"owner": "Administrator",
|
||||||
|
"permissions": [],
|
||||||
|
"quick_entry": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"read_only_onload": 0,
|
||||||
|
"show_name_in_global_search": 0,
|
||||||
|
"sort_field": "modified",
|
||||||
|
"sort_order": "DESC",
|
||||||
|
"track_changes": 0,
|
||||||
|
"track_seen": 0
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
|
# For license information, please see license.txt
|
||||||
|
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
import frappe
|
||||||
|
from frappe.model.document import Document
|
||||||
|
|
||||||
|
class WebFormField(Document):
|
||||||
|
pass
|
||||||
@@ -55,30 +55,26 @@
|
|||||||
<div class="centered">
|
<div class="centered">
|
||||||
<h1 class="title">ERPNext Foundation</h1>
|
<h1 class="title">ERPNext Foundation</h1>
|
||||||
<p class="intro-copy">ERPNext Foundation is a community of ERPNext Users, Developers and Service Providers. The goal of the ERPNext Foundation is to provide a platform for the ERPNext Community to come together, join hands and build assets to help build and enhance ERPNext around the world.</p>
|
<p class="intro-copy">ERPNext Foundation is a community of ERPNext Users, Developers and Service Providers. The goal of the ERPNext Foundation is to provide a platform for the ERPNext Community to come together, join hands and build assets to help build and enhance ERPNext around the world.</p>
|
||||||
<a href="" class="button button-secondary">Become a Member</a>
|
<a href="/members/details" class="button button-secondary">Become a Member</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<section class="feature">
|
<section class="feature">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="three-column left-aligned">
|
<div class="three-column left-aligned">
|
||||||
<div class="first-column">
|
<div class="columns">
|
||||||
<h1 class="subtitle">Events & Meetups</h1>
|
<h1 class="subtitle">Events & Meetups</h1>
|
||||||
<ul class="bulleted-list">
|
<ul class="bulleted-list list-circle">
|
||||||
<li>
|
{% for e in events %}
|
||||||
<a href="" class="secondary-link">2nd Indonesian Meetup</a>
|
<li>
|
||||||
</li>
|
<a href="{{ e.route }}" class="secondary-link">{{ frappe.format_date(e.event_date, "medium") }} - {{ e.event_title }}</a>
|
||||||
<li>
|
</li>
|
||||||
<a href="" class="secondary-link">2nd Indonesian Meetup</a>
|
{% endfor %}
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="/members" class="secondary-link">2nd Indonesian Meetup</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="second-column">
|
<div class="columns">
|
||||||
<h1 class="subtitle">Help Us Improve</h1>
|
<h1 class="subtitle">Help Us Improve</h1>
|
||||||
<ul class="bulleted-list">
|
<ul class="bulleted-list list-circle">
|
||||||
<li>
|
<li>
|
||||||
<a href="https://github.com/frappe/erpnext/tree/develop/erpnext/docs" class="secondary-link">Write Documentation</a>
|
<a href="https://github.com/frappe/erpnext/tree/develop/erpnext/docs" class="secondary-link">Write Documentation</a>
|
||||||
</li>
|
</li>
|
||||||
@@ -90,14 +86,14 @@
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="third-column">
|
<div class="columns">
|
||||||
<h1 class="subtitle">Need Help?</h1>
|
<h1 class="subtitle">Need Help?</h1>
|
||||||
<ul class="bulleted-list">
|
<ul class="bulleted-list list-circle">
|
||||||
<li>
|
<li>
|
||||||
<a href="" class="secondary-link">User Manual</a>
|
<a href="/docs/user/manual" class="secondary-link">User Manual</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="" class="secondary-link">Ask in our forum</a>
|
<a href="https://discuss.erpnext.com/" class="secondary-link">Ask in our forum</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="" class="secondary-link">Get Paid Support</a>
|
<a href="" class="secondary-link">Get Paid Support</a>
|
||||||
|
|||||||
10
foundation/www/index.py
Normal file
10
foundation/www/index.py
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
# See license.txt
|
||||||
|
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
import frappe
|
||||||
|
|
||||||
|
def get_context(context):
|
||||||
|
out = {
|
||||||
|
"events": frappe.get_all("Portal Event", fields=["event_title", "event_date", "details", "route"], filters=[["published", "=", 1]])
|
||||||
|
}
|
||||||
|
return out
|
||||||
Reference in New Issue
Block a user