Commit 63edb0e1 by aagusti

perbaikan binding

1 parent 7b78d4ba
...@@ -185,6 +185,8 @@ class BaseView(object): ...@@ -185,6 +185,8 @@ class BaseView(object):
buttons = self.buttons and self.buttons or buttons buttons = self.buttons and self.buttons or buttons
if "bindings" in kwargs and kwargs["bindings"]: if "bindings" in kwargs and kwargs["bindings"]:
bindings = kwargs["bindings"] bindings = kwargs["bindings"]
elif self.bindings:
bindings = self.bindings
else: else:
bindings = self.get_bindings(row) bindings = self.get_bindings(row)
form_params = {} form_params = {}
......
...@@ -4,10 +4,12 @@ import logging ...@@ -4,10 +4,12 @@ import logging
from deform.widget import ( from deform.widget import (
SchemaType, SchemaType,
DateInputWidget as DeformDateInputWidget, DateInputWidget as DeformDateInputWidget,
default_resources, ResourceRegistry, default_resource_registry) default_resources, ResourceRegistry, default_resource_registry, _StrippedString, Widget)
from colander import null, Invalid from colander import null, Invalid, SchemaNode, Mapping
_logging = logging.getLogger(__name__) _logging = logging.getLogger(__name__)
class _FieldStorage(SchemaType): class _FieldStorage(SchemaType):
def deserialize(self, node, cstruct): def deserialize(self, node, cstruct):
if cstruct in (null, None, '', b''): if cstruct in (null, None, '', b''):
...@@ -18,86 +20,6 @@ class _FieldStorage(SchemaType): ...@@ -18,86 +20,6 @@ class _FieldStorage(SchemaType):
return cstruct return cstruct
# class DateInputWidget(DeformDateInputWidget):
# """
# Renders a date picker widget.
#
# The default rendering is as a native HTML5 date input widget,
# falling back to pickadate (https://github.com/amsul/pickadate.js.)
#
# Most useful when the schema node is a ``colander.Date`` object.
#
# **Attributes/Arguments**
#
# options
# Dictionary of options for configuring the widget (eg: date format)
#
# template
# The template name used to render the widget. Default:
# ``dateinput``.
#
# readonly_template
# The template name used to render the widget in read-only mode.
# Default: ``readonly/textinput``.
# """
# requirements = {
# "js": (
# "deform:static/scripts/modernizr.custom.input-types-and-atts.js",
# "static/pickadate/lib/picker.js",
# "static/pickadate/lib/picker.date.js",
# "static/pickadate/lib/picker.time.js",
# "static/pickadate/lib/legacy.js",
# ),
# "css": (
# "static/pickadate/lib/themes/default.css",
# "static/pickadate/lib/themes/default.date.css",
# "static/pickadate/lib/themes/default.time.css",
# ),
# }
# default_options = (
# ("format", "yyyy-mm-dd"),
# ("selectMonths", True),
# ("selectYears", True),
# ("formatSubmit", "yyyy-mm-dd"),
# )
# def serialize(self, field, cstruct, **kw):
# if cstruct in (null, None):
# cstruct = ""
# readonly = kw.get("readonly", self.readonly)
# template = readonly and self.readonly_template or self.template
# options = dict(
# kw.get("options") or self.options or self.default_options
# )
# kw.setdefault("options_json", json.dumps(options))
# values = self.get_template_values(field, cstruct, kw)
# return field.renderer(template, **values)
#
# def deserialize(self, field, pstruct):
# logging.debug(f"widget: {field} {pstruct}")
# if pstruct in ("", null):
# return null
# try:
# validated = self._pstruct_schema.deserialize(pstruct)
# except Invalid as exc:
# raise Invalid(field.schema, "Invalid pstruct: %s" % exc)
# return validated["date_submit"] or validated["date"]
# default_resources["pickadate"] = \
# {
# None: {
# "js": (
# "static/pickadate/lib/picker.js",
# "static/pickadate/lib/picker.date.js",
# "static/pickadate/lib/picker.time.js",
# "static/pickadate/lib/legacy.js",
# ),
# "css": (
# "static/pickadate/lib/themes/default.css",
# "static/pickadate/lib/themes/default.date.css",
# "static/pickadate/lib/themes/default.time.css",
# ),
# }
# }
# default_resources = { # default_resources = {
# "jquery.form": {None: {"js": "deform:static/scripts/jquery.form-3.09.js"}}, # "jquery.form": {None: {"js": "deform:static/scripts/jquery.form-3.09.js"}},
# "jquery.maskedinput": { # "jquery.maskedinput": {
......
import json import json
import logging import logging
from colander import SchemaNode, null, Mapping, Invalid, text_, string_types from colander import SchemaNode, null, Mapping, Invalid, string_types
from deform.widget import Widget, _StrippedString, Select2Widget from deform.widget import Widget, _StrippedString, Select2Widget, default_resources, \
ResourceRegistry, default_resource_registry
from iso8601.iso8601 import ISO8601_REGEX
from deform.i18n import _
_logging = logging.getLogger(__name__) _logging = logging.getLogger(__name__)
...@@ -46,7 +49,7 @@ class DokumenWidget(Widget): ...@@ -46,7 +49,7 @@ class DokumenWidget(Widget):
try: try:
validated = self._pstruct_schema.deserialize(pstruct) validated = self._pstruct_schema.deserialize(pstruct)
except Invalid as exc: except Invalid as exc:
raise Invalid(field.schema, text_("Invalid pstruct: %s" % exc)) raise Invalid(field.schema, f"Invalid pstruct: {exc}")
jenis = validated["jenis"] jenis = validated["jenis"]
year = validated["year"] year = validated["year"]
bundle = validated["bundle"] bundle = validated["bundle"]
...@@ -101,7 +104,7 @@ class FormulirWidget(Widget): ...@@ -101,7 +104,7 @@ class FormulirWidget(Widget):
try: try:
validated = self._pstruct_schema.deserialize(pstruct) validated = self._pstruct_schema.deserialize(pstruct)
except Invalid as exc: except Invalid as exc:
raise Invalid(field.schema, text_("Invalid pstruct: %s" % exc)) raise Invalid(field.schema, f"Invalid pstruct: {exc}")
year = validated["year"] year = validated["year"]
bundle = validated["bundle"] bundle = validated["bundle"]
seq = validated["seq"] seq = validated["seq"]
...@@ -154,7 +157,7 @@ class BlokKavNoWidget(Widget): ...@@ -154,7 +157,7 @@ class BlokKavNoWidget(Widget):
try: try:
validated = self._pstruct_schema.deserialize(pstruct) validated = self._pstruct_schema.deserialize(pstruct)
except Invalid as exc: except Invalid as exc:
raise Invalid(field.schema, text_("Invalid pstruct: %s" % exc)) raise Invalid(field.schema, f"Invalid pstruct: {exc}")
blok_kav_no = validated["blok_kav_no"] blok_kav_no = validated["blok_kav_no"]
rt = validated["rt"] rt = validated["rt"]
rw = validated["rw"] rw = validated["rw"]
...@@ -187,6 +190,8 @@ class Select2MsWidget(Select2Widget): ...@@ -187,6 +190,8 @@ class Select2MsWidget(Select2Widget):
""" """
url = ""
slave = ""
template = "select2_ms.pt" template = "select2_ms.pt"
...@@ -221,7 +226,7 @@ class QtyWidget(Widget): ...@@ -221,7 +226,7 @@ class QtyWidget(Widget):
try: try:
validated = self._pstruct_schema.deserialize(pstruct) validated = self._pstruct_schema.deserialize(pstruct)
except Invalid as exc: except Invalid as exc:
raise Invalid(field.schema, text_("Invalid pstruct: %s" % exc)) raise Invalid(field.schema, f"Invalid pstruct: {exc}")
qty = validated["qty"] qty = validated["qty"]
measure = validated["measure"] measure = validated["measure"]
...@@ -493,3 +498,196 @@ class LeafMapWidget(Widget): ...@@ -493,3 +498,196 @@ class LeafMapWidget(Widget):
if not pstruct: if not pstruct:
return null return null
return pstruct return pstruct
class BootStrapDateInputWidget(Widget):
"""
Renders a date picker widget.
The default rendering is as a native HTML5 date input widget,
falling back to pickadate (https://github.com/amsul/pickadate.js.)
Most useful when the schema node is a ``colander.Date`` object.
**Attributes/Arguments**
options
Dictionary of options for configuring the widget (eg: date format)
template
The template name used to render the widget. Default:
``dateinput``.
readonly_template
The template name used to render the widget in read-only mode.
Default: ``readonly/textinput``.
"""
template = "bootstrapdateinput"
readonly_template = "readonly/textinput"
type_name = "text"
req_path = "opensipkd.base:static/v3/js/plugin"
requirements = (
('deform', None),
{
"js": (
f"{req_path}/bootstrap-datepicker/js/bootstrap-datepicker.min.js",
f"{req_path}/bootstrap-timepicker/bootstrap-timepicker.min.js",
f"{req_path}/bootstrap-datetimepicker/js/bootstrap-datetimepicker.min.js",
),
"css": (
f"{req_path}/bootstrap-datepicker/css/bootstrap-datepicker.min.css",
# f"{req_path}/bootstrap-timepicker/css/bootstrap-timepicker.min.css",
f"{req_path}/bootstrap-datetimepicker/css/bootstrap-datetimepicker.min.css",
),
}
)
default_options = (
("format", "yyyy-mm-dd"),
)
# ("selectMonths", True),
# ("selectYears", True),
options = None
_pstruct_schema = SchemaNode(
Mapping(),
SchemaNode(_StrippedString(), name="date"),
SchemaNode(_StrippedString(), name="date_submit", missing=""),
)
def serialize(self, field, cstruct, **kw):
if cstruct in (null, None):
cstruct = ""
readonly = kw.get("readonly", self.readonly)
template = readonly and self.readonly_template or self.template
options = dict(
kw.get("options") or self.options or self.default_options
)
options["formatSubmit"] = "yyyy-mm-dd"
kw.setdefault("options_json", json.dumps(options))
values = self.get_template_values(field, cstruct, kw)
return field.renderer(template, **values)
def deserialize(self, field, pstruct):
if pstruct in ("", null):
return null
try:
validated = self._pstruct_schema.deserialize(pstruct)
except Invalid as exc:
raise Invalid(field.schema, "Invalid pstruct: %s" % exc)
return validated["date_submit"] or validated["date"]
class BootStrapDateTimeInputWidget(Widget):
"""
Renders a datetime picker widget.
The default rendering is as a pair of inputs (a date and a time) using
pickadate.js (https://github.com/amsul/pickadate.js).
Used for ``colander.DateTime`` schema nodes.
**Attributes/Arguments**
date_options
A dictionary of date options passed to pickadate.
time_options
A dictionary of time options passed to pickadate.
template
The template name used to render the widget. Default:
``dateinput``.
readonly_template
The template name used to render the widget in read-only mode.
Default: ``readonly/textinput``.
"""
template = "datetimeinput"
readonly_template = "readonly/datetimeinput"
type_name = "datetime"
requirements = (("modernizr", None), ("pickadate", None))
default_date_options = (
("format", "yyyy-mm-dd"),
("selectMonths", True),
("selectYears", True),
)
date_options = None
default_time_options = (("format", "h:i A"), ("interval", 30))
time_options = None
_pstruct_schema = SchemaNode(
Mapping(),
SchemaNode(_StrippedString(), name="date"),
SchemaNode(_StrippedString(), name="time"),
SchemaNode(_StrippedString(), name="date_submit", missing=""),
SchemaNode(_StrippedString(), name="time_submit", missing=""),
)
def serialize(self, field, cstruct, **kw):
if cstruct in (null, None):
cstruct = ""
readonly = kw.get("readonly", self.readonly)
if cstruct:
parsed = ISO8601_REGEX.match(cstruct)
if parsed: # strip timezone if it's there
timezone = parsed.groupdict()["timezone"]
if timezone and cstruct.endswith(timezone):
cstruct = cstruct[: -len(timezone)]
try:
date, time = cstruct.split("T", 1)
try:
# get rid of milliseconds
time, _ = time.split(".", 1)
except ValueError:
pass
kw["date"], kw["time"] = date, time
except ValueError: # need more than one item to unpack
kw["date"] = kw["time"] = ""
date_options = dict(
kw.get("date_options")
or self.date_options
or self.default_date_options
)
date_options["formatSubmit"] = "yyyy-mm-dd"
kw["date_options_json"] = json.dumps(date_options)
time_options = dict(
kw.get("time_options")
or self.time_options
or self.default_time_options
)
time_options["formatSubmit"] = "HH:i"
kw["time_options_json"] = json.dumps(time_options)
values = self.get_template_values(field, cstruct, kw)
template = readonly and self.readonly_template or self.template
return field.renderer(template, **values)
def deserialize(self, field, pstruct):
if pstruct is null:
return null
else:
try:
validated = self._pstruct_schema.deserialize(pstruct)
except Invalid as exc:
raise Invalid(field.schema, "Invalid pstruct: %s" % exc)
# seriously pickadate? oh. right. i forgot. you're javascript.
date = validated["date_submit"] or validated["date"]
time = validated["time_submit"] or validated["time"]
if not time and not date:
return null
result = "T".join([date, time])
if not date:
raise Invalid(field.schema, _("Incomplete date"), result)
if not time:
raise Invalid(field.schema, _("Incomplete time"), result)
return result
<div tal:define="css_class css_class|field.widget.css_class;
oid oid|field.oid;
style style|field.widget.style;
type_name type_name|field.widget.type_name;"
tal:omit-tag="">
${field.start_mapping()}
<input type="${type_name}"
name="date"
value="${cstruct}"
tal:attributes="class string: ${css_class or ''} form-control hasDatepicker;
style style;
attributes|field.widget.attributes|{'readonly':'true'};"
id="${oid}"/>
${field.end_mapping()}
<script type="text/javascript">
deform.addCallback(
'${oid}',
function deform_cb(oid) {
$('#'+oid).datepicker(${options_json});
//if (!Modernizr.inputtypes['date'] ||"${type_name}" != "date" || window.forceDateTimePolyfill){
// $('#' + oid).pickadate(${options_json});
//}
}
);
</script>
</div>
<div tal:define=" <div tal:define="
name name|field.name; name name|field.name;
style field.widget.style; style field.widget.style;
oid oid|field.oid; oid oid|field.oid;
css_class css_class|field.widget.css_class; css_class css_class|field.widget.css_class;
unicode unicode|str; unicode unicode|str;
optgroup_class optgroup_class|field.widget.optgroup_class; optgroup_class optgroup_class|field.widget.optgroup_class;
multiple multiple|field.widget.multiple; multiple multiple|field.widget.multiple;
url url|field.widget.url; url url|field.widget.url;
slave slave|field.widget.slave;" slave slave|field.widget.slave;"
tal:omit-tag=""> tal:omit-tag="">
<style> <style>
.select2-selection.form-control { .select2-selection.form-control {
padding: 0px 0px; padding: 0px 0px;
} }
.select2-container--default .select2-selection--multiple, .select2-container--default .select2-selection--multiple,
.select2-container--default .select2-selection--single { .select2-container--default .select2-selection--single {
border: 1px solid #ccc; border: 1px solid #ccc;
} }
</style> </style>
<input type="hidden" name="__start__" value="${name}:sequence" <input type="hidden" name="__start__" value="${name}:sequence"
tal:condition="multiple" /> tal:condition="multiple" />
<select tal:attributes=" <select tal:attributes="
name name; name name;
id oid; id oid;
class string: form-control ${css_class or ''}; class string: form-control ${css_class or ''};
data-placeholder field.widget.placeholder|None; data-placeholder field.widget.placeholder|None;
multiple multiple; multiple multiple;
style style; style style;
attributes|field.widget.attributes|{};"> attributes|field.widget.attributes|{};">
<tal:loop tal:repeat="item values"> <tal:loop tal:repeat="item values">
<optgroup tal:condition="isinstance(item, optgroup_class)" <optgroup tal:condition="isinstance(item, optgroup_class)"
tal:attributes="label item.label"> tal:attributes="label item.label">
<option tal:repeat="(value, description) item.options" <option tal:repeat="(value, description) item.options"
tal:attributes=" tal:attributes="
selected python:field.widget.get_select_value(cstruct, value); selected python:field.widget.get_select_value(cstruct, value);
class css_class; class css_class;
label field.widget.long_label_generator and description; label field.widget.long_label_generator and description;
value value" value value"
tal:content="field.widget.long_label_generator and field.widget.long_label_generator(item.label, description) or description"/> tal:content="field.widget.long_label_generator and field.widget.long_label_generator(item.label, description) or description"/>
</optgroup> </optgroup>
<option tal:condition="not isinstance(item, optgroup_class)" <option tal:condition="not isinstance(item, optgroup_class)"
tal:attributes=" tal:attributes="
selected python:field.widget.get_select_value(cstruct, item[0]); selected python:field.widget.get_select_value(cstruct, item[0]);
class css_class; class css_class;
value item[0]">${item[1]}</option> value item[0]">${item[1]}</option>
</tal:loop> </tal:loop>
</select> </select>
<script type="text/javascript"> <script type="text/javascript">
deform.addCallback( deform.addCallback(
'${field.oid}', '${field.oid}',
function(oid) { function (oid) {
$('#' + oid).select2({ $('#' + oid).select2({
containerCssClass: 'form-control', containerCssClass: 'form-control',
placeholder: "${str(field.widget.placeholder).replace('"','\\"')|""}" || undefined, placeholder: "${str(field.widget.placeholder).replace('"','\\"')|""}" || undefined,
allowClear: "${hasattr(field.widget, 'placeholder')}", allowClear: "${hasattr(field.widget, 'placeholder')}",
tags: ${str(getattr(field.widget, 'tags', 'undefined')).lower()} tags: ${str(getattr(field.widget, 'tags', 'undefined')).lower()}
}); });
} }
); );
</script> </script>
<script type="text/javascript" tal:condition="url and slave"> <script type="text/javascript" tal:condition="url and slave">
deform.addCallback( deform.addCallback(
'${field.oid}', '${field.oid}',
function(oid) { function (oid) {
$('#' + oid).change(function () { $('#' + oid).change(function () {
$("#${slave}").val(""); $("#${slave}").val("");
$("#${slave}").empty(); $("#${slave}").empty();
$("#${slave}").append('<option value="" selected disabled>Pilih Data...</option>'); $("#${slave}").append('<option value="" selected disabled>Pilih Data...</option>');
let value = $(this).val(); let value = $(this).val();
if (value) { if (value) {
$.ajax({ $.ajax({
type: "GET", type: "GET",
url: "${url}" + value, url: "${url}" + value,
success: function (res) { success: function (res) {
if (res) { if (res) {
$.each(res, function (key, value) { console.log(res);
$("#${slave}").append('<option value="' + key + '">' + value + '</option>'); $.each(res, function (key, value) {
}); console.log(key);
} else { console.log(value);
$("#${slave}").empty(); $("#${slave}").append('<option value="' + key + '">' + value + '</option>');
} });
} else {
$("#${slave}").empty();
}
}
});
} }
$("#${slave}").change();
}); });
} });
$("#${slave}").change();
});
});
</script> </script>
<input type="hidden" name="__end__" value="${name}:sequence" <input type="hidden" name="__end__" value="${name}:sequence"
tal:condition="multiple" /> tal:condition="multiple" />
</div> </div>
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!