Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
erp5
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Tomáš Peterka
erp5
Commits
d2f8c300
Commit
d2f8c300
authored
Dec 05, 2017
by
Tomáš Peterka
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
WWIP
parent
45641950
Changes
10
Show whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
396 additions
and
299 deletions
+396
-299
bt5/erp5_hal_json_style/SkinTemplateItem/portal_skins/erp5_hal_json_style/ERP5Document_getHateoas.py
...rtal_skins/erp5_hal_json_style/ERP5Document_getHateoas.py
+219
-147
bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_jio_js.js
...athTemplateItem/web_page_module/rjs_gadget_erp5_jio_js.js
+25
-23
bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_jio_js.xml
...thTemplateItem/web_page_module/rjs_gadget_erp5_jio_js.xml
+2
-2
bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_listbox_html.html
...ateItem/web_page_module/rjs_gadget_erp5_listbox_html.html
+5
-9
bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_listbox_html.xml
...lateItem/web_page_module/rjs_gadget_erp5_listbox_html.xml
+2
-2
bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_listbox_js.js
...emplateItem/web_page_module/rjs_gadget_erp5_listbox_js.js
+85
-66
bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_listbox_js.xml
...mplateItem/web_page_module/rjs_gadget_erp5_listbox_js.xml
+2
-2
bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_nojqm_css.css
...emplateItem/web_page_module/rjs_gadget_erp5_nojqm_css.css
+23
-14
bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_nojqm_css.xml
...emplateItem/web_page_module/rjs_gadget_erp5_nojqm_css.xml
+2
-2
bt5/erp5_web_renderjs_ui/SkinTemplateItem/portal_skins/erp5_web_renderjs_ui/erp5css.less.txt
...teItem/portal_skins/erp5_web_renderjs_ui/erp5css.less.txt
+31
-32
No files found.
bt5/erp5_hal_json_style/SkinTemplateItem/portal_skins/erp5_hal_json_style/ERP5Document_getHateoas.py
View file @
d2f8c300
...
@@ -21,8 +21,13 @@ Only in mode == 'form'
...
@@ -21,8 +21,13 @@ Only in mode == 'form'
Only in mode == 'traverse'
Only in mode == 'traverse'
TBD.
# Form
When handling form, we can expect field values to be stored in REQUEST.form in two forms
- raw string value under key "field_" + <field.id>
- python-object parsed from raw values under <field.id>
"""
"""
from
ZTUtils
import
make_query
from
ZTUtils
import
make_query
import
json
import
json
from
base64
import
urlsafe_b64encode
,
urlsafe_b64decode
from
base64
import
urlsafe_b64encode
,
urlsafe_b64decode
...
@@ -35,13 +40,32 @@ import re
...
@@ -35,13 +40,32 @@ import re
from
zExceptions
import
Unauthorized
from
zExceptions
import
Unauthorized
from
Products.ERP5Type.Utils
import
UpperCase
from
Products.ERP5Type.Utils
import
UpperCase
from
Products.ZSQLCatalog.SQLCatalog
import
Query
,
ComplexQuery
from
Products.ZSQLCatalog.SQLCatalog
import
Query
,
ComplexQuery
from
Products.ERP5Type.Log
import
log
MARKER
=
[]
if
REQUEST
is
None
:
if
REQUEST
is
None
:
REQUEST
=
context
.
REQUEST
REQUEST
=
context
.
REQUEST
# raise Unauthorized
if
response
is
None
:
if
response
is
None
:
response
=
REQUEST
.
RESPONSE
response
=
REQUEST
.
RESPONSE
def
toBasicTypes
(
obj
):
"""Ensure that obj contains only basic types."""
if
obj
is
None
:
return
obj
if
isinstance
(
obj
,
(
bool
,
int
,
float
,
long
,
str
,
unicode
)):
return
obj
if
isinstance
(
obj
,
(
tuple
,
list
)):
return
[
toBasicTypes
(
x
)
for
x
in
obj
]
try
:
return
{
toBasicTypes
(
key
):
toBasicTypes
(
obj
[
key
])
for
key
in
obj
}
except
:
log
(
'Cannot convert {!s} to basic types {!s}'
.
format
(
type
(
obj
),
obj
),
level
=
100
)
return
obj
# http://stackoverflow.com/a/13105359
# http://stackoverflow.com/a/13105359
def
byteify
(
string
):
def
byteify
(
string
):
if
isinstance
(
string
,
dict
):
if
isinstance
(
string
,
dict
):
...
@@ -53,11 +77,12 @@ def byteify(string):
...
@@ -53,11 +77,12 @@ def byteify(string):
else
:
else
:
return
string
return
string
def
ensure_serializable
(
obj
):
def
ensureSerializable
(
obj
):
"""Ensure obj and all sub-objects are JSON serializable."""
"""Ensure obj and all sub-objects are JSON serializable."""
if
isinstance
(
obj
,
dict
):
if
isinstance
(
obj
,
dict
):
for
key
in
obj
:
for
key
in
obj
:
obj
[
key
]
=
ensure
_s
erializable
(
obj
[
key
])
obj
[
key
]
=
ensure
S
erializable
(
obj
[
key
])
# throw away date's type information and later reconstruct as Zope's DateTime
# throw away date's type information and later reconstruct as Zope's DateTime
if
isinstance
(
obj
,
DateTime
):
if
isinstance
(
obj
,
DateTime
):
return
obj
.
ISO
()
return
obj
.
ISO
()
...
@@ -66,17 +91,18 @@ def ensure_serializable(obj):
...
@@ -66,17 +91,18 @@ def ensure_serializable(obj):
# we don't check other isinstances - we believe that iterables don't contain unserializable objects
# we don't check other isinstances - we believe that iterables don't contain unserializable objects
return
obj
return
obj
datetime_iso_re
=
re
.
compile
(
r'^\
d{
4}-\
d{
2}-\
d{
2} |T\
d{
2}:\
d{
2}:\
d{
2}.*$'
)
datetime_iso_re
=
re
.
compile
(
r'^\
d{
4}-\
d{
2}-\
d{
2} |T\
d{
2}:\
d{
2}:\
d{
2}.*$'
)
time_iso_re
=
re
.
compile
(
r'^(\
d{
2}):(\
d{
2}):(\
d{
2}).*$'
)
time_iso_re
=
re
.
compile
(
r'^(\
d{
2}):(\
d{
2}):(\
d{
2}).*$'
)
def
ensure
_d
eserialized
(
obj
):
def
ensure
D
eserialized
(
obj
):
"""Deserialize classes serialized by our own `ensure
_s
erializable`.
"""Deserialize classes serialized by our own `ensure
S
erializable`.
Method `biteify` must not be called on the result because it would revert out
Method `biteify` must not be called on the result because it would revert out
deserialization by calling __str__ on constructed classes.
deserialization by calling __str__ on constructed classes.
"""
"""
if
isinstance
(
obj
,
dict
):
if
isinstance
(
obj
,
dict
):
for
key
in
obj
:
for
key
in
obj
:
obj
[
key
]
=
ensure
_d
eserialized
(
obj
[
key
])
obj
[
key
]
=
ensure
D
eserialized
(
obj
[
key
])
# seems that default __str__ method is good enough
# seems that default __str__ method is good enough
if
isinstance
(
obj
,
str
):
if
isinstance
(
obj
,
str
):
# Zope's DateTime must be good enough for everyone
# Zope's DateTime must be good enough for everyone
...
@@ -97,16 +123,49 @@ def getProtectedProperty(document, select):
...
@@ -97,16 +123,49 @@ def getProtectedProperty(document, select):
See https://lab.nexedi.com/nexedi/erp5/blob/master/product/ERP5Form/ListBox.py#L2293
See https://lab.nexedi.com/nexedi/erp5/blob/master/product/ERP5Form/ListBox.py#L2293
"""
"""
try
:
try
:
if
"."
in
select
:
#see https://lab.nexedi.com/nexedi/erp5/blob/master/product/ERP5Form/ListBox.py#L2293
try
:
select
=
select
[
select
.
rindex
(
'.'
)
+
1
:]
select
=
select
[
select
.
rindex
(
'.'
)
+
1
:]
except
ValueError
:
pass
return
document
.
getProperty
(
select
,
d
=
None
)
return
document
.
getProperty
(
select
,
d
=
None
)
except
(
ConflictError
,
RuntimeError
):
except
(
ConflictError
,
RuntimeError
):
raise
raise
except
:
except
:
return
None
return
None
def
kwargsForCallable
(
func
,
initial_kwargs
,
kwargs_dict
):
"""Create a copy of `kwargs_dict` with only items suitable for `func`.
In case the function cannot state required arguments it throws an AttributeError.
"""
func_param_list
=
[
func_param
.
strip
()
for
func_param
in
func
.
params
().
split
(
","
)]
func_param_name_list
=
[
func_param
if
'='
not
in
func_param
else
func_param
.
split
(
'='
)[
0
]
for
func_param
in
func_param_list
if
'*'
not
in
func_param
]
for
func_param_name
in
func_param_name_list
:
if
func_param_name
in
kwargs_dict
and
func_param_name
not
in
initial_kwargs
:
initial_kwargs
[
func_param_name
]
=
kwargs_dict
.
get
(
func_param_name
)
# MIDDLE-DANGEROUS!
# In case of reports (later even exports) substitute None for unknown
# parameters. We suppose Python syntax for parameters!
# What we do here is literally putting every form field from `kwargs_dict`
# into search method parameters - this is later put back into `kwargs_dict`
# this way we can mimic synchronous rendering when all form field values
# were available in `kwargs_dict`. It is obviously wrong behaviour.
for
func_param
in
func_param_list
:
if
"*"
in
func_param
:
continue
if
"="
in
func_param
:
continue
# now we have only mandatory parameters
func_param
=
func_param
.
strip
()
if
func_param
not
in
initial_kwargs
:
initial_kwargs
[
func_param
]
=
None
return
initial_kwargs
def
object_uids_and_accessors
(
search_result
,
result_index
,
traversed_document
):
def
anythingUidAndAccessor
(
search_result
,
result_index
,
traversed_document
):
"""Return unique ID, unique URL, getter and hasser for any combination of `search_result` and `index`.
"""Return unique ID, unique URL, getter and hasser for any combination of `search_result` and `index`.
You want to use this method when you need a unique reference to random object in iterable (for example
You want to use this method when you need a unique reference to random object in iterable (for example
...
@@ -121,8 +180,9 @@ def object_uids_and_accessors(search_result, result_index, traversed_document):
...
@@ -121,8 +180,9 @@ def object_uids_and_accessors(search_result, result_index, traversed_document):
result[uid] = {'url': portal.abolute_url() + url}
result[uid] = {'url': portal.abolute_url() + url}
value = getter(random_object, "value")
value = getter(random_object, "value")
"""
"""
context
.
log
(
"anythingUidAndAccessor({!s}#type:{!s}, {:d}, {!s}"
.
format
(
search_result
,
type
(
search_result
),
result_index
,
traversed_document
))
if
hasattr
(
search_result
,
"getObject"
):
if
hasattr
(
search_result
,
"getObject"
):
#
search_result = search_result.getObject()
#
"Brain" object - which simulates DB Cursor thus result must have UID
contents_uid
=
search_result
.
uid
contents_uid
=
search_result
.
uid
# every document indexed in catalog has to have relativeUrl
# every document indexed in catalog has to have relativeUrl
contents_relative_url
=
getRealRelativeUrl
(
search_result
)
contents_relative_url
=
getRealRelativeUrl
(
search_result
)
...
@@ -133,7 +193,7 @@ def object_uids_and_accessors(search_result, result_index, traversed_document):
...
@@ -133,7 +193,7 @@ def object_uids_and_accessors(search_result, result_index, traversed_document):
try
:
try
:
return
doc
.
hasProperty
(
attr
)
return
doc
.
hasProperty
(
attr
)
except
(
AttributeError
,
Unauthorized
)
as
e
:
except
(
AttributeError
,
Unauthorized
)
as
e
:
context
.
log
(
'Cannot state ownership of property "{}" on {!s} because of "{!s}"'
.
format
(
log
(
'Cannot state ownership of property "{}" on {!s} because of "{!s}"'
.
format
(
attr
,
doc
,
e
))
attr
,
doc
,
e
))
return
False
return
False
elif
hasattr
(
search_result
,
"aq_self"
):
elif
hasattr
(
search_result
,
"aq_self"
):
...
@@ -162,11 +222,12 @@ def object_uids_and_accessors(search_result, result_index, traversed_document):
...
@@ -162,11 +222,12 @@ def object_uids_and_accessors(search_result, result_index, traversed_document):
return
contents_uid
,
contents_relative_url
,
search_property_getter
,
search_property_hasser
return
contents_uid
,
contents_relative_url
,
search_property_getter
,
search_property_hasser
def
resolve_field
(
search_result
,
select
,
search_property_getter
,
search_property_hasser
):
def
getAttrFromAnything
(
search_result
,
select
,
search_property_getter
,
search_property_hasser
,
kwargs
):
"""Given `data_source` extract
fields defined in `field_list` and render them using `field_template_dict`
.
"""Given `data_source` extract
value named `select` using helper getter/hasser
.
:param data_source: any dict-like object (usually dict or Brain or Document)
:param data_source: any dict-like object (usually dict or Brain or Document)
:select: field name (can represent actual Properties or Scripts)
:select: field name (can represent actual attributes, Properties or even Scripts)
:kwargs: available arguments for possible callables hidden under `select`
"""
"""
# if the variable does not have a field template we need to find its
# if the variable does not have a field template we need to find its
...
@@ -175,7 +236,7 @@ def resolve_field(search_result, select, search_property_getter, search_property
...
@@ -175,7 +236,7 @@ def resolve_field(search_result, select, search_property_getter, search_property
contents_value
=
None
contents_value
=
None
if
not
isinstance
(
select
,
(
str
,
unicode
))
or
len
(
select
)
==
0
:
if
not
isinstance
(
select
,
(
str
,
unicode
))
or
len
(
select
)
==
0
:
context
.
log
(
'There is an invalid column name "{!s}"!'
.
format
(
select
),
level
=
200
)
log
(
'There is an invalid column name "{!s}"!'
.
format
(
select
),
level
=
200
)
return
None
return
None
if
"."
in
select
:
if
"."
in
select
:
...
@@ -211,7 +272,7 @@ def resolve_field(search_result, select, search_property_getter, search_property
...
@@ -211,7 +272,7 @@ def resolve_field(search_result, select, search_property_getter, search_property
# do not call it here - it will be done later in generic call part
# do not call it here - it will be done later in generic call part
contents_value
=
getattr
(
search_result
,
accessor_name
)
contents_value
=
getattr
(
search_result
,
accessor_name
)
except
(
AttributeError
,
KeyError
,
Unauthorized
)
as
error
:
except
(
AttributeError
,
KeyError
,
Unauthorized
)
as
error
:
context
.
log
(
"Could not evaluate {} nor {} on {} with error {!s}"
.
format
(
log
(
"Could not evaluate {} nor {} on {} with error {!s}"
.
format
(
select
,
accessor_name
,
search_result
,
error
),
level
=
100
)
# WARNING
select
,
accessor_name
,
search_result
,
error
),
level
=
100
)
# WARNING
if
contents_value
is
None
and
search_property_hasser
(
search_result
,
select
):
if
contents_value
is
None
and
search_property_hasser
(
search_result
,
select
):
...
@@ -222,7 +283,7 @@ def resolve_field(search_result, select, search_property_getter, search_property
...
@@ -222,7 +283,7 @@ def resolve_field(search_result, select, search_property_getter, search_property
try
:
try
:
contents_value
=
getattr
(
search_result
,
select
,
None
)
contents_value
=
getattr
(
search_result
,
select
,
None
)
except
(
Unauthorized
,
AttributeError
,
KeyError
)
as
error
:
except
(
Unauthorized
,
AttributeError
,
KeyError
)
as
error
:
context
.
log
(
"Cannot resolve {} on {!s} because {!s}"
.
format
(
log
(
"Cannot resolve {} on {!s} because {!s}"
.
format
(
select
,
raw_search_result
,
error
),
level
=
100
)
select
,
raw_search_result
,
error
),
level
=
100
)
if
callable
(
contents_value
):
if
callable
(
contents_value
):
...
@@ -242,7 +303,7 @@ def resolve_field(search_result, select, search_property_getter, search_property
...
@@ -242,7 +303,7 @@ def resolve_field(search_result, select, search_property_getter, search_property
else
:
else
:
contents_value
=
contents_value
()
contents_value
=
contents_value
()
except
(
AttributeError
,
KeyError
,
Unauthorized
)
as
error
:
except
(
AttributeError
,
KeyError
,
Unauthorized
)
as
error
:
context
.
log
(
"Could not evaluate {} on {} with error {!s}"
.
format
(
log
(
"Could not evaluate {} on {} with error {!s}"
.
format
(
contents_value
,
search_result
,
error
),
level
=
100
)
# WARNING
contents_value
,
search_result
,
error
),
level
=
100
)
# WARNING
# make resulting value JSON serializable
# make resulting value JSON serializable
...
@@ -309,12 +370,15 @@ def getFormRelativeUrl(form):
...
@@ -309,12 +370,15 @@ def getFormRelativeUrl(form):
)[
0
].
relative_url
)[
0
].
relative_url
def
getFieldDefault
(
traversed_document
,
field
,
key
,
value
=
None
):
def
getFieldDefault
(
form
,
field
,
key
,
value
=
None
):
# REQUEST.get(field.id, field.get_value("default"))
"""Get available value for `field` preferably in python-object from REQUEST or from field's default."""
result
=
traversed_document
.
Field_getDefaultValue
(
field
,
key
,
value
,
REQUEST
)
if
value
is
None
:
if
getattr
(
result
,
'translate'
,
None
)
is
not
None
:
value
=
REQUEST
.
form
.
get
(
field
.
id
,
REQUEST
.
form
.
get
(
key
,
None
))
or
field
.
get_value
(
'default'
)
result
=
"%s"
%
result
if
field
.
has_value
(
"unicode"
)
and
field
.
get_value
(
"unicode"
)
and
isinstance
(
value
,
'unicode'
):
return
result
value
=
unicode
(
value
,
self
.
get_form_encoding
())
if
getattr
(
value
,
'translate'
,
None
)
is
not
None
:
return
"%s"
%
value
return
value
def
renderField
(
traversed_document
,
field
,
form
,
value
=
None
,
meta_type
=
None
,
key
=
None
,
key_prefix
=
None
,
selection_params
=
None
):
def
renderField
(
traversed_document
,
field
,
form
,
value
=
None
,
meta_type
=
None
,
key
=
None
,
key_prefix
=
None
,
selection_params
=
None
):
...
@@ -328,6 +392,13 @@ def renderField(traversed_document, field, form, value=None, meta_type=None, key
...
@@ -328,6 +392,13 @@ def renderField(traversed_document, field, form, value=None, meta_type=None, key
if
key
is
None
:
if
key
is
None
:
key
=
field
.
generate_field_key
(
key_prefix
=
key_prefix
)
key
=
field
.
generate_field_key
(
key_prefix
=
key_prefix
)
if
meta_type
==
"ProxyField"
:
# resolve the base meta_type
meta_type
=
field
.
getRecursiveTemplateField
().
meta_type
# some TALES expressions are using Base_getRelatedObjectParameter which requires that
previous_request_field
=
REQUEST
.
other
.
pop
(
'field_id'
,
None
)
REQUEST
.
other
[
'field_id'
]
=
field
.
id
result
=
{
result
=
{
"type"
:
meta_type
,
"type"
:
meta_type
,
"title"
:
Base_translateString
(
field
.
get_value
(
"title"
)),
"title"
:
Base_translateString
(
field
.
get_value
(
"title"
)),
...
@@ -342,15 +413,10 @@ def renderField(traversed_document, field, form, value=None, meta_type=None, key
...
@@ -342,15 +413,10 @@ def renderField(traversed_document, field, form, value=None, meta_type=None, key
# fields have default value and can be required (unlike boxes)
# fields have default value and can be required (unlike boxes)
result
.
update
({
result
.
update
({
"required"
:
field
.
get_value
(
"required"
)
if
field
.
has_value
(
"required"
)
else
None
,
"required"
:
field
.
get_value
(
"required"
)
if
field
.
has_value
(
"required"
)
else
None
,
"default"
:
getFieldDefault
(
traversed_document
,
field
,
result
[
"key"
]
,
value
),
"default"
:
getFieldDefault
(
form
,
field
,
key
,
value
),
})
})
if
meta_type
==
"ProxyField"
:
# start the actuall "switch" on field's meta_type here
return
renderField
(
traversed_document
,
field
,
form
,
value
,
meta_type
=
field
.
getRecursiveTemplateField
().
meta_type
,
key
=
key
,
key_prefix
=
key_prefix
,
selection_params
=
selection_params
)
if
meta_type
in
(
"ListField"
,
"RadioField"
,
"ParallelListField"
,
"MultiListField"
):
if
meta_type
in
(
"ListField"
,
"RadioField"
,
"ParallelListField"
,
"MultiListField"
):
result
.
update
({
result
.
update
({
# XXX Message can not be converted to json as is
# XXX Message can not be converted to json as is
...
@@ -371,9 +437,8 @@ def renderField(traversed_document, field, form, value=None, meta_type=None, key
...
@@ -371,9 +437,8 @@ def renderField(traversed_document, field, form, value=None, meta_type=None, key
"sub_select_key"
:
traversed_document
.
Field_getSubFieldKeyDict
(
field
,
'default:list'
,
key
=
result
[
"key"
]),
"sub_select_key"
:
traversed_document
.
Field_getSubFieldKeyDict
(
field
,
'default:list'
,
key
=
result
[
"key"
]),
"sub_input_key"
:
"default_"
+
traversed_document
.
Field_getSubFieldKeyDict
(
field
,
'default:list:int'
,
key
=
result
[
"key"
])
"sub_input_key"
:
"default_"
+
traversed_document
.
Field_getSubFieldKeyDict
(
field
,
'default:list:int'
,
key
=
result
[
"key"
])
})
})
return
result
if
meta_type
in
(
"StringField"
,
"FloatField"
,
"EmailField"
,
"TextAreaField"
,
el
if
meta_type
in
(
"StringField"
,
"FloatField"
,
"EmailField"
,
"TextAreaField"
,
"LinesField"
,
"ImageField"
,
"FileField"
,
"IntegerField"
,
"LinesField"
,
"ImageField"
,
"FileField"
,
"IntegerField"
,
"PasswordField"
,
"EditorField"
):
"PasswordField"
,
"EditorField"
):
if
meta_type
==
"FloatField"
:
if
meta_type
==
"FloatField"
:
...
@@ -396,9 +461,8 @@ def renderField(traversed_document, field, form, value=None, meta_type=None, key
...
@@ -396,9 +461,8 @@ def renderField(traversed_document, field, form, value=None, meta_type=None, key
if
v
))
if
v
))
if
parameters
:
if
parameters
:
result
[
"default"
]
=
'%s?%s'
%
(
result
[
"default"
],
parameters
)
result
[
"default"
]
=
'%s?%s'
%
(
result
[
"default"
],
parameters
)
return
result
if
meta_type
==
"DateTimeField"
:
el
if
meta_type
==
"DateTimeField"
:
result
.
update
({
result
.
update
({
"date_only"
:
field
.
get_value
(
"date_only"
),
"date_only"
:
field
.
get_value
(
"date_only"
),
"ampm_time_style"
:
field
.
get_value
(
"ampm_time_style"
),
"ampm_time_style"
:
field
.
get_value
(
"ampm_time_style"
),
...
@@ -407,7 +471,7 @@ def renderField(traversed_document, field, form, value=None, meta_type=None, key
...
@@ -407,7 +471,7 @@ def renderField(traversed_document, field, form, value=None, meta_type=None, key
"hide_day"
:
field
.
get_value
(
'hide_day'
),
"hide_day"
:
field
.
get_value
(
'hide_day'
),
"hidden_day_is_last_day"
:
field
.
get_value
(
'hidden_day_is_last_day'
),
"hidden_day_is_last_day"
:
field
.
get_value
(
'hidden_day_is_last_day'
),
})
})
date_value
=
getFieldDefault
(
traversed_document
,
field
,
result
[
"key"
]
,
value
)
date_value
=
getFieldDefault
(
form
,
field
,
key
,
value
)
if
not
date_value
and
field
.
get_value
(
'default_now'
):
if
not
date_value
and
field
.
get_value
(
'default_now'
):
date_value
=
DateTime
()
date_value
=
DateTime
()
if
same_type
(
date_value
,
DateTime
()):
if
same_type
(
date_value
,
DateTime
()):
...
@@ -418,9 +482,8 @@ def renderField(traversed_document, field, form, value=None, meta_type=None, key
...
@@ -418,9 +482,8 @@ def renderField(traversed_document, field, form, value=None, meta_type=None, key
result
[
"default"
]
=
date_value
result
[
"default"
]
=
date_value
for
subkey
in
(
"year"
,
"month"
,
"day"
,
"hour"
,
"minute"
,
"ampm"
,
"timezone"
):
for
subkey
in
(
"year"
,
"month"
,
"day"
,
"hour"
,
"minute"
,
"ampm"
,
"timezone"
):
result
[
"subfield_%s_key"
%
subkey
]
=
traversed_document
.
Field_getSubFieldKeyDict
(
field
,
subkey
,
key
=
result
[
"key"
])
result
[
"subfield_%s_key"
%
subkey
]
=
traversed_document
.
Field_getSubFieldKeyDict
(
field
,
subkey
,
key
=
result
[
"key"
])
return
result
if
meta_type
in
(
"RelationStringField"
,
"MultiRelationStringField"
):
el
if
meta_type
in
(
"RelationStringField"
,
"MultiRelationStringField"
):
portal_type_list
=
field
.
get_value
(
'portal_type'
)
portal_type_list
=
field
.
get_value
(
'portal_type'
)
translated_portal_type
=
[]
translated_portal_type
=
[]
jump_reference_list
=
[]
jump_reference_list
=
[]
...
@@ -462,11 +525,16 @@ def renderField(traversed_document, field, form, value=None, meta_type=None, key
...
@@ -462,11 +525,16 @@ def renderField(traversed_document, field, form, value=None, meta_type=None, key
for
(
listbox_path
,
listbox_name
)
in
listbox_ids
:
for
(
listbox_path
,
listbox_name
)
in
listbox_ids
:
(
listbox_form_name
,
listbox_field_name
)
=
listbox_path
.
split
(
'/'
,
2
)
(
listbox_form_name
,
listbox_field_name
)
=
listbox_path
.
split
(
'/'
,
2
)
form
=
getattr
(
context
,
listbox_form_name
)
# do not override "global" `form`
rel_form
=
getattr
(
context
,
listbox_form_name
)
# find listbox field
# find listbox field
listbox_form_field
=
filter
(
lambda
f
:
f
.
getId
()
==
listbox_field_name
,
form
.
get_fields
())[
0
]
listbox_form_field
=
filter
(
lambda
f
:
f
.
getId
()
==
listbox_field_name
,
rel_form
.
get_fields
())[
0
]
rel_cache
=
{
'form_id'
:
REQUEST
.
get
(
'form_id'
,
MARKER
),
'field_id'
:
REQUEST
.
get
(
'field_id'
,
MARKER
)}
REQUEST
.
set
(
'form_id'
,
rel_form
.
id
)
REQUEST
.
set
(
'field_id'
,
listbox_form_field
.
id
)
# get original definition
# get original definition
subfield
=
renderField
(
context
,
listbox_form_field
,
form
)
subfield
=
renderField
(
context
,
listbox_form_field
,
rel_
form
)
# overwrite, like Base_getRelatedObjectParameter does
# overwrite, like Base_getRelatedObjectParameter does
if
subfield
[
"portal_type"
]
==
[]:
if
subfield
[
"portal_type"
]
==
[]:
subfield
[
"portal_type"
]
=
field
.
get_value
(
'portal_type'
)
subfield
[
"portal_type"
]
=
field
.
get_value
(
'portal_type'
)
...
@@ -488,6 +556,11 @@ def renderField(traversed_document, field, form, value=None, meta_type=None, key
...
@@ -488,6 +556,11 @@ def renderField(traversed_document, field, form, value=None, meta_type=None, key
subfield
[
"column_list"
].
append
((
tmp_column
[
0
],
Base_translateString
(
tmp_column
[
1
])))
subfield
[
"column_list"
].
append
((
tmp_column
[
0
],
Base_translateString
(
tmp_column
[
1
])))
listbox
[
Base_translateString
(
listbox_name
)]
=
subfield
listbox
[
Base_translateString
(
listbox_name
)]
=
subfield
for
key
in
rel_cache
:
if
rel_cache
[
key
]
is
not
MARKER
:
REQUEST
.
set
(
key
,
rel_cache
[
key
])
result
.
update
({
result
.
update
({
"url"
:
relative_url
,
"url"
:
relative_url
,
"translated_portal_types"
:
translated_portal_type
,
"translated_portal_types"
:
translated_portal_type
,
...
@@ -508,21 +581,18 @@ def renderField(traversed_document, field, form, value=None, meta_type=None, key
...
@@ -508,21 +581,18 @@ def renderField(traversed_document, field, form, value=None, meta_type=None, key
"relation_item_key"
:
traversed_document
.
Field_getSubFieldKeyDict
(
field
,
"item"
,
key
=
result
[
"key"
]),
"relation_item_key"
:
traversed_document
.
Field_getSubFieldKeyDict
(
field
,
"item"
,
key
=
result
[
"key"
]),
"relation_item_relative_url"
:
[
jump_reference
.
getRelativeUrl
()
for
jump_reference
in
jump_reference_list
]
"relation_item_relative_url"
:
[
jump_reference
.
getRelativeUrl
()
for
jump_reference
in
jump_reference_list
]
})
})
return
result
if
meta_type
in
(
"CheckBoxField"
,
"MultiCheckBoxField"
):
el
if
meta_type
in
(
"CheckBoxField"
,
"MultiCheckBoxField"
):
if
meta_type
==
"MultiCheckBoxField"
:
if
meta_type
==
"MultiCheckBoxField"
:
result
[
"items"
]
=
field
.
get_value
(
"items"
),
result
[
"items"
]
=
field
.
get_value
(
"items"
),
return
result
if
meta_type
==
"GadgetField"
:
el
if
meta_type
==
"GadgetField"
:
result
.
update
({
result
.
update
({
"url"
:
field
.
get_value
(
"gadget_url"
),
"url"
:
field
.
get_value
(
"gadget_url"
),
"sandbox"
:
field
.
get_value
(
"js_sandbox"
)
"sandbox"
:
field
.
get_value
(
"js_sandbox"
)
})
})
return
result
if
meta_type
==
"ListBox"
:
el
if
meta_type
==
"ListBox"
:
"""Display list of objects with optional search/sort capabilities on columns from catalog.
"""Display list of objects with optional search/sort capabilities on columns from catalog.
We might be inside a ReportBox which is inside a parent form BUT we still have access to
We might be inside a ReportBox which is inside a parent form BUT we still have access to
...
@@ -576,8 +646,8 @@ def renderField(traversed_document, field, form, value=None, meta_type=None, key
...
@@ -576,8 +646,8 @@ def renderField(traversed_document, field, form, value=None, meta_type=None, key
# Search for non-editable documents - all reports goes here
# Search for non-editable documents - all reports goes here
# Reports have custom search scripts which wants parameters from the form
# Reports have custom search scripts which wants parameters from the form
# thus we introspect such parameters and try to find them in REQUEST
# thus we introspect such parameters and try to find them in REQUEST
list_method
=
None
list_method
=
field
.
get_value
(
'list_method'
)
or
None
list_method_name
=
traversed_document
.
Listbox_getListMethodName
(
field
)
list_method_name
=
list_method
.
getMethodName
()
if
list_method
is
not
None
else
""
if
list_method_name
not
in
(
""
,
"portal_catalog"
,
"searchFolder"
,
"objectValues"
):
if
list_method_name
not
in
(
""
,
"portal_catalog"
,
"searchFolder"
,
"objectValues"
):
# we avoid accessing known protected objects and builtin functions above
# we avoid accessing known protected objects and builtin functions above
try
:
try
:
...
@@ -585,32 +655,15 @@ def renderField(traversed_document, field, form, value=None, meta_type=None, key
...
@@ -585,32 +655,15 @@ def renderField(traversed_document, field, form, value=None, meta_type=None, key
except
(
Unauthorized
,
AttributeError
,
ValueError
)
as
error
:
except
(
Unauthorized
,
AttributeError
,
ValueError
)
as
error
:
# we are touching some specially protected (usually builtin) methods
# we are touching some specially protected (usually builtin) methods
# which we will not introspect
# which we will not introspect
context
.
log
(
'ListBox {!s} list_method {} is unavailable because of "{!s}"'
.
format
(
log
(
'ListBox {!s} list_method {} is unavailable because of "{!s}"'
.
format
(
field
,
list_method_name
,
error
),
level
=
100
)
field
,
list_method_name
,
error
),
level
=
100
)
else
:
list_method
=
None
# Put all ListBox's search method params from REQUEST to `default_param_json`
# Put all ListBox's search method params from REQUEST to `default_param_json`
# because old code expects synchronous render thus having all form's values
# because old code expects synchronous render thus having all form's values
# still in the request which is not our case because we do asynchronous rendering
# still in the request which is not our case because we do asynchronous rendering
if
list_method
is
not
None
and
hasattr
(
list_method
,
"ZScriptHTML_tryParams"
):
if
list_method
is
not
None
:
for
list_method_param
in
list_method
.
ZScriptHTML_tryParams
():
kwargsForCallable
(
list_method
,
list_method_query_dict
,
REQUEST
)
if
list_method_param
in
REQUEST
and
list_method_param
not
in
list_method_query_dict
:
list_method_query_dict
[
list_method_param
]
=
REQUEST
.
get
(
list_method_param
)
# MIDDLE-DANGEROUS!
# In case of reports (later even exports) substitute None for unknown
# parameters. We suppose Python syntax for parameters!
# What we do here is literally putting every form field from REQUEST
# into search method parameters - this is later put back into REQUEST
# this way we can mimic synchronous rendering when all form field values
# were available in REQUEST. It is obviously wrong behaviour.
for
list_method_param
in
list_method
.
params
().
split
(
","
):
if
"*"
in
list_method_param
:
continue
if
"="
in
list_method_param
:
continue
# now we have only mandatory parameters
list_method_param
=
list_method_param
.
strip
()
if
list_method_param
not
in
list_method_query_dict
:
list_method_query_dict
[
list_method_param
]
=
None
# Now if the list_method does not specify **kwargs we need to remove
# Now if the list_method does not specify **kwargs we need to remove
# unwanted parameters like "portal_type" which is everywhere
# unwanted parameters like "portal_type" which is everywhere
if
"**"
not
in
list_method
.
params
():
if
"**"
not
in
list_method
.
params
():
...
@@ -627,7 +680,7 @@ def renderField(traversed_document, field, form, value=None, meta_type=None, key
...
@@ -627,7 +680,7 @@ def renderField(traversed_document, field, form, value=None, meta_type=None, key
"form_relative_url"
:
"%s/%s"
%
(
getFormRelativeUrl
(
form
),
field
.
id
),
"form_relative_url"
:
"%s/%s"
%
(
getFormRelativeUrl
(
form
),
field
.
id
),
"list_method"
:
list_method_name
,
"list_method"
:
list_method_name
,
"default_param_json"
:
urlsafe_b64encode
(
"default_param_json"
:
urlsafe_b64encode
(
json
.
dumps
(
ensure
_s
erializable
(
list_method_query_dict
)))
json
.
dumps
(
ensure
S
erializable
(
list_method_query_dict
)))
}
}
# once we imprint `default_params` into query string of 'list method' we
# once we imprint `default_params` into query string of 'list method' we
# don't want them to propagate to the query as well
# don't want them to propagate to the query as well
...
@@ -642,29 +695,10 @@ def renderField(traversed_document, field, form, value=None, meta_type=None, key
...
@@ -642,29 +695,10 @@ def renderField(traversed_document, field, form, value=None, meta_type=None, key
"script_id"
:
script
.
id
,
"script_id"
:
script
.
id
,
"relative_url"
:
traversed_document
.
getRelativeUrl
().
replace
(
"/"
,
"%2F"
),
"relative_url"
:
traversed_document
.
getRelativeUrl
().
replace
(
"/"
,
"%2F"
),
"list_method"
:
list_method_name
,
"list_method"
:
list_method_name
,
"default_param_json"
:
urlsafe_b64encode
(
json
.
dumps
(
ensure
_s
erializable
(
list_method_query_dict
)))
"default_param_json"
:
urlsafe_b64encode
(
json
.
dumps
(
ensure
S
erializable
(
list_method_query_dict
)))
}
}
list_method_query_dict
=
{}
list_method_query_dict
=
{}
# row_list = list_method(limit=lines, portal_type=portal_types,
# **default_params)
# line_list = []
# for row in row_list:
# document = row.getObject()
# line = {
# "url": url_template_dict["document_hal"] % {
# "root_url": site_root.absolute_url(),
# "relative_url": document.getRelativeUrl(),
# "script_id": script.id
# }
# }
# for property, title in columns:
# prop = document.getProperty(property)
# if same_type(prop, DateTime()):
# prop = "XXX Serialize DateTime"
# line[title] = prop
# line["_relative_url"] = document.getRelativeUrl()
# line_list.append(line)
result
.
update
({
result
.
update
({
"column_list"
:
column_list
,
"column_list"
:
column_list
,
"search_column_list"
:
search_column_list
,
"search_column_list"
:
search_column_list
,
...
@@ -674,7 +708,7 @@ def renderField(traversed_document, field, form, value=None, meta_type=None, key
...
@@ -674,7 +708,7 @@ def renderField(traversed_document, field, form, value=None, meta_type=None, key
"show_anchor"
:
field
.
get_value
(
"anchor"
),
"show_anchor"
:
field
.
get_value
(
"anchor"
),
"portal_type"
:
portal_type_list
,
"portal_type"
:
portal_type_list
,
"lines"
:
field
.
get_value
(
'lines'
),
"lines"
:
field
.
get_value
(
'lines'
),
"default_params"
:
ensure
_s
erializable
(
default_params
),
"default_params"
:
ensure
S
erializable
(
default_params
),
"list_method"
:
list_method_name
,
"list_method"
:
list_method_name
,
"show_stat"
:
field
.
get_value
(
'stat_method'
)
!=
""
or
len
(
field
.
get_value
(
'stat_columns'
))
>
0
,
"show_stat"
:
field
.
get_value
(
'stat_method'
)
!=
""
or
len
(
field
.
get_value
(
'stat_columns'
))
>
0
,
"show_count"
:
field
.
get_value
(
'count_method'
)
!=
""
,
"show_count"
:
field
.
get_value
(
'count_method'
)
!=
""
,
...
@@ -686,9 +720,8 @@ def renderField(traversed_document, field, form, value=None, meta_type=None, key
...
@@ -686,9 +720,8 @@ def renderField(traversed_document, field, form, value=None, meta_type=None, key
})
})
if
(
list_method_custom
is
not
None
):
if
(
list_method_custom
is
not
None
):
result
[
"list_method_template"
]
=
list_method_custom
result
[
"list_method_template"
]
=
list_method_custom
return
result
if
meta_type
==
"FormBox"
:
el
if
meta_type
==
"FormBox"
:
embedded_document
=
{
embedded_document
=
{
'_links'
:
{},
'_links'
:
{},
'_actions'
:
{},
'_actions'
:
{},
...
@@ -711,9 +744,8 @@ def renderField(traversed_document, field, form, value=None, meta_type=None, key
...
@@ -711,9 +744,8 @@ def renderField(traversed_document, field, form, value=None, meta_type=None, key
result
[
'_embedded'
]
=
{
result
[
'_embedded'
]
=
{
'_view'
:
embedded_document
'_view'
:
embedded_document
}
}
return
result
if
meta_type
==
"MatrixBox"
:
el
if
meta_type
==
"MatrixBox"
:
# data are generated by python code for MatrixBox.py
# data are generated by python code for MatrixBox.py
# template_fields are better rendered here because they can be part of "hidden"
# template_fields are better rendered here because they can be part of "hidden"
# group which is not rendered in form by default. Including
# group which is not rendered in form by default. Including
...
@@ -726,10 +758,14 @@ def renderField(traversed_document, field, form, value=None, meta_type=None, key
...
@@ -726,10 +758,14 @@ def renderField(traversed_document, field, form, value=None, meta_type=None, key
for
template_field
in
template_field_names
for
template_field
in
template_field_names
if
template_field
in
form
},
if
template_field
in
form
},
})
})
return
result
else
:
# All other fields are not implemented and we'll return only basic info about them
# All other fields are not implemented and we'll return only basic info about them
result
[
"_debug"
]
=
"Unknown field type "
+
meta_type
result
[
"_debug"
]
=
"Unknown field type "
+
meta_type
if
previous_request_field
is
not
None
:
REQUEST
.
other
[
'field_id'
]
=
previous_request_field
return
result
return
result
...
@@ -740,7 +776,12 @@ def renderForm(traversed_document, form, response_dict, key_prefix=None, selecti
...
@@ -740,7 +776,12 @@ def renderForm(traversed_document, form, response_dict, key_prefix=None, selecti
we mitigate the functionality here by overriding ListBox's own values
we mitigate the functionality here by overriding ListBox's own values
for columns, editable columns, and sort with those found in `selection_params`
for columns, editable columns, and sort with those found in `selection_params`
"""
"""
previous_request_other
=
{
'form_id'
:
REQUEST
.
other
.
pop
(
'form_id'
,
None
),
'here'
:
REQUEST
.
other
.
pop
(
'here'
,
None
)
}
REQUEST
.
set
(
'here'
,
traversed_document
)
REQUEST
.
set
(
'here'
,
traversed_document
)
REQUEST
.
set
(
'form_id'
,
form
.
id
)
field_errors
=
REQUEST
.
get
(
'field_errors'
,
{})
field_errors
=
REQUEST
.
get
(
'field_errors'
,
{})
#hardcoded
#hardcoded
...
@@ -860,6 +901,7 @@ def renderForm(traversed_document, form, response_dict, key_prefix=None, selecti
...
@@ -860,6 +901,7 @@ def renderForm(traversed_document, form, response_dict, key_prefix=None, selecti
if
report_item
.
selection_name
:
if
report_item
.
selection_name
:
selection_name
=
report_prefix
+
"_"
+
report_item
.
selection_name
selection_name
=
report_prefix
+
"_"
+
report_item
.
selection_name
context
.
log
(
'Report {} defines selection_name {}'
.
format
(
report_title
,
selection_name
))
report_form_params
.
update
(
selection_name
=
selection_name
)
report_form_params
.
update
(
selection_name
=
selection_name
)
# this should load selections with correct values - since it is modifying
# this should load selections with correct values - since it is modifying
# global state in the backend we have nothing more to do here
# global state in the backend we have nothing more to do here
...
@@ -892,6 +934,11 @@ def renderForm(traversed_document, form, response_dict, key_prefix=None, selecti
...
@@ -892,6 +934,11 @@ def renderForm(traversed_document, form, response_dict, key_prefix=None, selecti
report_result
[
'title'
]
=
report_title
report_result
[
'title'
]
=
report_title
report_result_list
.
append
(
report_result
)
report_result_list
.
append
(
report_result
)
response_dict
[
'report_section_list'
]
=
report_result_list
response_dict
[
'report_section_list'
]
=
report_result_list
# end-if report_section
for
key
,
value
in
previous_request_other
.
items
():
if
value
is
not
None
:
REQUEST
.
set
(
key
,
value
)
# XXX form action update, etc
# XXX form action update, etc
def
renderRawField
(
field
):
def
renderRawField
(
field
):
...
@@ -1329,7 +1376,7 @@ def calculateHateoas(is_portal=None, is_site_root=None, traversed_document=None,
...
@@ -1329,7 +1376,7 @@ def calculateHateoas(is_portal=None, is_site_root=None, traversed_document=None,
#
#
# Possible call arguments example:
# Possible call arguments example:
# form_relative_url: portal_skins/erp5_web/WebSite_view/listbox
# form_relative_url: portal_skins/erp5_web/WebSite_view/listbox
# list_method:
objectValues
(Script providing items)
# list_method:
"objectValues"
(Script providing items)
# default_param_json: <base64 encoded JSON> (Additional search params)
# default_param_json: <base64 encoded JSON> (Additional search params)
# query: <str> (term for fulltext search)
# query: <str> (term for fulltext search)
# select_list: ['int_index', 'id', 'title', ...] (column names to select)
# select_list: ['int_index', 'id', 'title', ...] (column names to select)
...
@@ -1351,6 +1398,9 @@ def calculateHateoas(is_portal=None, is_site_root=None, traversed_document=None,
...
@@ -1351,6 +1398,9 @@ def calculateHateoas(is_portal=None, is_site_root=None, traversed_document=None,
response
.
setStatus
(
405
)
response
.
setStatus
(
405
)
return
""
return
""
# set 'here' for field rendering which contain TALES expressions
REQUEST
.
set
(
'here'
,
traversed_document
)
# in case we have custom list method
# in case we have custom list method
catalog_kw
=
{}
catalog_kw
=
{}
...
@@ -1374,7 +1424,7 @@ def calculateHateoas(is_portal=None, is_site_root=None, traversed_document=None,
...
@@ -1374,7 +1424,7 @@ def calculateHateoas(is_portal=None, is_site_root=None, traversed_document=None,
}
}
if
default_param_json
is
not
None
:
if
default_param_json
is
not
None
:
catalog_kw
.
update
(
catalog_kw
.
update
(
ensure
_d
eserialized
(
ensure
D
eserialized
(
byteify
(
byteify
(
json
.
loads
(
urlsafe_b64decode
(
default_param_json
)))))
json
.
loads
(
urlsafe_b64decode
(
default_param_json
)))))
if
query
:
if
query
:
...
@@ -1392,7 +1442,7 @@ def calculateHateoas(is_portal=None, is_site_root=None, traversed_document=None,
...
@@ -1392,7 +1442,7 @@ def calculateHateoas(is_portal=None, is_site_root=None, traversed_document=None,
sort_order
=
"DESC"
sort_order
=
"DESC"
else
:
else
:
# should raise an ValueError instead
# should raise an ValueError instead
context
.
log
(
'Wrong sort order "{}" in {}! It must start with "asc" or "desc"'
.
format
(
sort_order
,
form_relative_url
),
log
(
'Wrong sort order "{}" in {}! It must start with "asc" or "desc"'
.
format
(
sort_order
,
form_relative_url
),
level
=
200
)
# error
level
=
200
)
# error
return
(
sort_col
,
sort_order
)
return
(
sort_col
,
sort_order
)
...
@@ -1414,7 +1464,7 @@ def calculateHateoas(is_portal=None, is_site_root=None, traversed_document=None,
...
@@ -1414,7 +1464,7 @@ def calculateHateoas(is_portal=None, is_site_root=None, traversed_document=None,
#
#
# for k, v in catalog_kw.items():
# for k, v in catalog_kw.items():
# REQUEST.set(k, v)
# REQUEST.set(k, v)
context
.
log
(
'list_method >>> {}({!s})'
.
format
(
list_method
,
catalog_kw
))
search_result_iterable
=
callable_list_method
(
**
catalog_kw
)
search_result_iterable
=
callable_list_method
(
**
catalog_kw
)
# Cast to list if only one element is provided
# Cast to list if only one element is provided
...
@@ -1438,6 +1488,10 @@ def calculateHateoas(is_portal=None, is_site_root=None, traversed_document=None,
...
@@ -1438,6 +1488,10 @@ def calculateHateoas(is_portal=None, is_site_root=None, traversed_document=None,
listbox_field_id
=
source_field
.
id
listbox_field_id
=
source_field
.
id
# XXX Proxy field are not correctly handled in traversed_document of web site
# XXX Proxy field are not correctly handled in traversed_document of web site
listbox_form
=
getattr
(
traversed_document
,
source_field
.
aq_parent
.
id
)
listbox_form
=
getattr
(
traversed_document
,
source_field
.
aq_parent
.
id
)
# field TALES expression evaluated by Base_getRelatedObjectParameter requires that
REQUEST
.
other
[
'form_id'
]
=
listbox_form
.
id
for
select
in
select_list
:
for
select
in
select_list
:
# See Listbox.py getValueList --> getEditableField & getColumnAliasList method
# See Listbox.py getValueList --> getEditableField & getColumnAliasList method
# In short: there are Form Field definitions which names start with
# In short: there are Form Field definitions which names start with
...
@@ -1473,13 +1527,15 @@ def calculateHateoas(is_portal=None, is_site_root=None, traversed_document=None,
...
@@ -1473,13 +1527,15 @@ def calculateHateoas(is_portal=None, is_site_root=None, traversed_document=None,
if
result_index
>=
start
+
num_items
:
if
result_index
>=
start
+
num_items
:
break
break
# we can render fields which need 'here' to be set to currently rendered document
#REQUEST.set('here', search_result)
contents_item
=
{}
contents_uid
,
contents_relative_url
,
property_getter
,
property_hasser
=
\
contents_uid
,
contents_relative_url
,
property_getter
,
property_hasser
=
\
object_uids_and_accessors
(
search_result
,
result_index
,
traversed_document
)
anythingUidAndAccessor
(
search_result
,
result_index
,
traversed_document
)
# this dict will hold all resolved values
# _links.self.href is mandatory for JIO so it can create reference to the
contents_item
=
{
# (listbox) item alone
'_links'
:
{
contents_item
[
'_links'
]
=
{
# _links.self.href is mandatory for JIO so it can create reference to items alone
'self'
:
{
'self'
:
{
"href"
:
default_document_uri_template
%
{
"href"
:
default_document_uri_template
%
{
"root_url"
:
site_root
.
absolute_url
(),
"root_url"
:
site_root
.
absolute_url
(),
...
@@ -1488,7 +1544,7 @@ def calculateHateoas(is_portal=None, is_site_root=None, traversed_document=None,
...
@@ -1488,7 +1544,7 @@ def calculateHateoas(is_portal=None, is_site_root=None, traversed_document=None,
},
},
},
},
}
}
}
# ERP5 stores&send the list of editable elements in a hidden field called
# ERP5 stores&send the list of editable elements in a hidden field called
# only database results can be editable so it belongs here
# only database results can be editable so it belongs here
if
editable_field_dict
and
listbox_field_id
:
if
editable_field_dict
and
listbox_field_id
:
...
@@ -1505,10 +1561,17 @@ def calculateHateoas(is_portal=None, is_site_root=None, traversed_document=None,
...
@@ -1505,10 +1561,17 @@ def calculateHateoas(is_portal=None, is_site_root=None, traversed_document=None,
REQUEST
.
set
(
'cell'
,
search_result
)
REQUEST
.
set
(
'cell'
,
search_result
)
# if default value is given by evaluating Tales expression then we only
# if default value is given by evaluating Tales expression then we only
# put "cell" to request (expected by tales) and let the field evaluate
# put "cell" to request (expected by tales) and let the field evaluate
default_field_value
=
None
if
getattr
(
editable_field_dict
[
select
].
tales
,
"default"
,
""
)
==
""
:
if
getattr
(
editable_field_dict
[
select
].
tales
,
"default"
,
""
)
==
""
:
# if there is no tales expr (or is empty) we extract the value from search result
# if there is no tales expr (or is empty) we extract the value from search result
default_field_value
=
getProtectedProperty
(
search_result
,
select
)
default_field_value
=
getAttrFromAnything
(
search_result
,
select
,
property_getter
,
property_hasser
,
{})
context
.
log
(
'renderField!for"{}"({!s}, field={!s}, form={!s}, value={!s}, key={}'
.
format
(
select
,
traversed_document
,
editable_field_dict
[
select
],
listbox_form
,
default_field_value
,
'field_%s_%s'
%
(
editable_field_dict
[
select
].
id
,
contents_uid
)))
contents_item
[
select
]
=
renderField
(
contents_item
[
select
]
=
renderField
(
traversed_document
,
traversed_document
,
...
@@ -1522,13 +1585,11 @@ def calculateHateoas(is_portal=None, is_site_root=None, traversed_document=None,
...
@@ -1522,13 +1585,11 @@ def calculateHateoas(is_portal=None, is_site_root=None, traversed_document=None,
# most of the complicated magic happens here - we need to resolve field names
# most of the complicated magic happens here - we need to resolve field names
# given search_result. This name can unfortunately mean almost anything from
# given search_result. This name can unfortunately mean almost anything from
# a key name to Python Script with variable number of input parameters.
# a key name to Python Script with variable number of input parameters.
contents_item
[
select
]
=
resolve_field
(
search_result
,
select
,
property_getter
,
property_hasser
)
contents_item
[
select
]
=
getAttrFromAnything
(
search_result
,
select
,
property_getter
,
property_hasser
,
{
'brain'
:
search_result
}
)
# endfor select
# endfor select
contents_list
.
append
(
contents_item
)
contents_list
.
append
(
contents_item
)
result_dict
[
'_embedded'
].
update
({
result_dict
[
'_embedded'
][
'contents'
]
=
ensureSerializable
(
contents_list
)
'contents'
:
contents_list
})
# Compute statistics if the search issuer was ListBox
# Compute statistics if the search issuer was ListBox
# or in future if the stats (SUM) are required by JIO call
# or in future if the stats (SUM) are required by JIO call
...
@@ -1536,8 +1597,6 @@ def calculateHateoas(is_portal=None, is_site_root=None, traversed_document=None,
...
@@ -1536,8 +1597,6 @@ def calculateHateoas(is_portal=None, is_site_root=None, traversed_document=None,
if
source_field_meta_type
==
"ProxyField"
:
if
source_field_meta_type
==
"ProxyField"
:
source_field_meta_type
=
source_field
.
getRecursiveTemplateField
().
meta_type
source_field_meta_type
=
source_field
.
getRecursiveTemplateField
().
meta_type
context
.
log
(
'source_field "{!s}", source_field_meta_type {!s}'
.
format
(
source_field
,
source_field_meta_type
))
if
source_field
is
not
None
and
source_field_meta_type
==
"ListBox"
:
if
source_field
is
not
None
and
source_field_meta_type
==
"ListBox"
:
contents_stat_list
=
[]
contents_stat_list
=
[]
# in case the search was issued by listbox we can provide results of
# in case the search was issued by listbox we can provide results of
...
@@ -1546,37 +1605,34 @@ def calculateHateoas(is_portal=None, is_site_root=None, traversed_document=None,
...
@@ -1546,37 +1605,34 @@ def calculateHateoas(is_portal=None, is_site_root=None, traversed_document=None,
stat_method
=
source_field
.
get_value
(
'stat_method'
)
stat_method
=
source_field
.
get_value
(
'stat_method'
)
stat_columns
=
source_field
.
get_value
(
'stat_columns'
)
stat_columns
=
source_field
.
get_value
(
'stat_columns'
)
context
.
log
(
'stat_method "{!s}", stat_columns {!s}'
.
format
(
stat_method
,
stat_columns
))
context
.
log
(
'stat_method "{!s}", stat_columns {!s}'
.
format
(
stat_method
,
stat_columns
))
# Selection is unfortunatelly required fot stat methods
# support only selection_name for stat methods because any `selection` is deprecated
# and should be removed
selection_name
=
source_field
.
get_value
(
'selection_name'
)
selection_name
=
source_field
.
get_value
(
'selection_name'
)
selection
=
None
if
selection_name
and
'selection_name'
not
in
catalog_kw
:
if
selection_name
:
catalog_kw
[
'selection_name'
]
=
selection_name
selection_tool
=
context
.
getPortalObject
().
portal_selections
context
.
log
(
'stat_method will receive selection_name "{}"'
.
format
(
catalog_kw
[
'selection_name'
]))
selection
=
selection_tool
.
getSelectionFor
(
selection_name
,
REQUEST
)
contents_stat
=
{}
contents_stat
=
{}
if
len
(
stat_columns
)
>
0
:
if
len
(
stat_columns
)
>
0
:
# prefer stat per columns as it is in ListBox
# prefer stat per column (follow original ListBox.py implementation)
# always called on current context
for
stat_name
,
stat_script
in
stat_columns
:
for
stat_name
,
stat_script
in
stat_columns
:
contents_stat
[
stat_name
]
=
getattr
(
traversed_document
,
stat_script
)(
contents_stat
[
stat_name
]
=
getattr
(
traversed_document
,
stat_script
)(
**
catalog_kw
)
selection
=
selection
,
selection_name
=
selection_name
,
**
catalog_kw
)
contents_stat_list
.
append
(
contents_stat
)
contents_stat_list
.
append
(
contents_stat
)
elif
stat_method
!=
""
and
stat_method
.
getMethodName
()
!=
list_method
:
elif
stat_method
!=
""
and
stat_method
.
getMethodName
()
!=
list_method
:
# general stat_method is second - should return dictionary or list of dictionaries
# general stat_method is second in priority list - should return dictionary or list of dictionaries
# where all "fields" should be accessible by their "select" name
# where all "fields" should be accessible by their "select" name (no "listbox_" prefix)
contents_stat_list
=
getattr
(
traversed_document
,
stat_method
.
getMethodName
())(
**
catalog_kw
)
stat_method_result
=
getattr
(
traversed_document
,
stat_method
.
getMethodName
())(
**
catalog_kw
)
contents_stat_list
=
toBasicTypes
(
stat_method_result
)
or
[]
for
contents_stat
in
contents_stat_list
:
for
contents_stat
in
contents_stat_list
:
for
key
,
value
in
contents_stat
.
items
():
for
key
,
value
in
contents_stat
.
items
():
if
key
in
editable_field_dict
:
if
key
in
editable_field_dict
:
contents_stat
[
key
]
=
renderField
(
contents_stat
[
key
]
=
renderField
(
traversed_document
,
editable_field_dict
[
key
],
listbox_form
,
value
,
key
=
editable_field_dict
[
key
].
id
+
'__sum'
)
traversed_document
,
editable_field_dict
[
key
],
listbox_form
,
value
,
key
=
editable_field_dict
[
key
].
id
+
'__sum'
)
context
.
log
(
'contents_stat_list {!s}'
.
format
(
contents_stat_list
))
for
contents_stat
in
contents_stat_list
:
for
key
,
value
in
contents_stat
.
items
():
context
.
log
(
'contents_stat["{}"] = type {!s}, value {!s}'
.
format
(
key
,
type
(
value
),
value
))
if
len
(
contents_stat_list
)
>
0
:
if
len
(
contents_stat_list
)
>
0
:
result_dict
[
'_embedded'
].
update
({
result_dict
[
'_embedded'
][
'sum'
]
=
ensureSerializable
(
contents_stat_list
)
'sum'
:
contents_stat_list
})
# We should cleanup the selection if it exists in catalog params BUT
# We should cleanup the selection if it exists in catalog params BUT
# we cannot because it requires escalated Permission.'modifyPortal' so
# we cannot because it requires escalated Permission.'modifyPortal' so
...
@@ -1683,6 +1739,7 @@ def calculateHateoas(is_portal=None, is_site_root=None, traversed_document=None,
...
@@ -1683,6 +1739,7 @@ def calculateHateoas(is_portal=None, is_site_root=None, traversed_document=None,
return result_dict
return result_dict
response.setHeader('
Content
-
Type
', mime_type)
response.setHeader('
Content
-
Type
', mime_type)
context.log('
calculateHateoas
(
traversed_document
=
{
!
s
},
mode
=
"{}"'.format(temp_traversed_document, mode))
hateoas = calculateHateoas(is_portal=temp_is_portal, is_site_root=temp_is_site_root,
hateoas = calculateHateoas(is_portal=temp_is_portal, is_site_root=temp_is_site_root,
traversed_document=temp_traversed_document,
traversed_document=temp_traversed_document,
relative_url=relative_url,
relative_url=relative_url,
...
@@ -1692,7 +1749,22 @@ hateoas = calculateHateoas(is_portal=temp_is_portal, is_site_root=temp_is_site_r
...
@@ -1692,7 +1749,22 @@ hateoas = calculateHateoas(is_portal=temp_is_portal, is_site_root=temp_is_site_r
default_param_json=default_param_json,
default_param_json=default_param_json,
form_relative_url=form_relative_url)
form_relative_url=form_relative_url)
def deepInspection(obj, prefix):
if isinstance(obj, dict):
for key, value in obj.items():
if type(key) != str:
log('
{}
key
"{!s}"
:
type
{
!
s
}
'.format(prefix, key, type(key)))
deepInspection(value, prefix + '
.
' + str(key))
elif isinstance(obj, (tuple, list)):
for value in obj:
deepInspection(value, prefix)
elif obj is None or isinstance(obj, (str, int)):
return
else:
log('
{}
value
"{!s}"
,
type
{
!
s
}
'.format(prefix, obj, type(obj)))
if hateoas == "":
if hateoas == "":
return hateoas
return hateoas
else:
else:
# deepInspection(hateoas, '')
return json.dumps(hateoas, indent=2)
return json.dumps(hateoas, indent=2)
bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_jio_js.js
View file @
d2f8c300
...
@@ -178,31 +178,33 @@
...
@@ -178,31 +178,33 @@
]
]
)
)
.
push
(
function
(
catalog_json
)
{
.
push
(
function
(
catalog_json
)
{
var
data
=
catalog_json
.
_embedded
.
contents
,
var
data
=
catalog_json
.
_embedded
.
contents
||
[],
summary
=
catalog_json
.
_embedded
.
sum
,
summary
=
catalog_json
.
_embedded
.
sum
||
[],
count
=
catalog_json
.
_embedded
.
count
,
count
=
catalog_json
.
_embedded
.
count
;
length
=
data
.
length
,
return
{
k
,
"
data
"
:
{
uri
,
"
rows
"
:
data
.
map
(
function
(
item
)
{
item
,
var
uri
=
new
URI
(
item
.
_links
.
self
.
href
);
result
=
[];
for
(
k
=
0
;
k
<
length
;
k
+=
1
)
{
item
=
data
[
k
];
uri
=
new
URI
(
item
.
_links
.
self
.
href
);
delete
item
.
_links
;
delete
item
.
_links
;
result
.
push
({
id
:
uri
.
segment
(
2
),
doc
:
{},
value
:
item
});
}
return
{
return
{
data
:
{
"
id
"
:
uri
.
segment
(
2
),
rows
:
result
,
"
doc
"
:
{},
total_rows
:
result
.
length
"
value
"
:
item
};
}),
"
total_rows
"
:
data
.
length
},
"
sum
"
:
{
"
rows
"
:
summary
.
map
(
function
(
item
,
index
)
{
return
{
"
id
"
:
'
/#summary
'
+
index
,
// this is obviously wrong. @Romain help please!
"
doc
"
:
{},
"
value
"
:
item
};
}),
"
total_rows
"
:
summary
.
length
},
},
sum
:
summary
,
"
count
"
:
count
count
:
count
};
};
});
});
})
})
...
...
bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_jio_js.xml
View file @
d2f8c300
...
@@ -230,7 +230,7 @@
...
@@ -230,7 +230,7 @@
</item>
</item>
<item>
<item>
<key>
<string>
serial
</string>
</key>
<key>
<string>
serial
</string>
</key>
<value>
<string>
963.5
0499.50100.12458
</string>
</value>
<value>
<string>
963.5
9331.40212.55432
</string>
</value>
</item>
</item>
<item>
<item>
<key>
<string>
state
</string>
</key>
<key>
<string>
state
</string>
</key>
...
@@ -248,7 +248,7 @@
...
@@ -248,7 +248,7 @@
</tuple>
</tuple>
<state>
<state>
<tuple>
<tuple>
<float>
151
1939345.58
</float>
<float>
151
2454358.33
</float>
<string>
UTC
</string>
<string>
UTC
</string>
</tuple>
</tuple>
</state>
</state>
...
...
bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_listbox_html.html
View file @
d2f8c300
...
@@ -63,7 +63,7 @@
...
@@ -63,7 +63,7 @@
<
/a
>
<
/a
>
{{
/
if
}}
{{
/
if
}}
{{
else
}}
{{
else
}}
<
a
href
=
"
{{href}}
"
class
=
"
ui-link
"
>
{{
tex
t
}}
<
/a
>
<
a
href
=
"
{{href}}
"
class
=
"
ui-link
"
>
{{
defaul
t
}}
<
/a
>
{{
/
if
}}
{{
/
if
}}
<
/td
>
<
/td
>
{{
/
each
}}
{{
/
each
}}
...
@@ -124,7 +124,7 @@
...
@@ -124,7 +124,7 @@
{{
#
each
row_list
}}
{{
#
each
row_list
}}
<
tr
>
<
tr
>
{{
#
if
..
/
show_anchor
}}
{{
#
if
..
/
show_anchor
}}
<
td
><
/td
>
<
td
>
Total
<
/td
>
{{
/
if
}}
{{
/
if
}}
{{
#
each
cell_list
}}
{{
#
each
cell_list
}}
<
td
>
<
td
>
...
@@ -142,13 +142,9 @@
...
@@ -142,13 +142,9 @@
</script>
</script>
<script
id=
"listbox-nav-template"
type=
"text/x-handlebars-template"
>
<script
id=
"listbox-nav-template"
type=
"text/x-handlebars-template"
>
<
nav
class
=
"
ui-bar-inherit ui-controlgroup ui-controlgroup-horizontal ui-corner-all ui-paging-menu
"
>
<
div
class
=
"
ui-controlgroup-controls
"
>
<
a
class
=
"
{{previous_classname}}
"
data
-
i18n
=
"
Previous
"
href
=
"
{{previous_url}}
"
>
Previous
<
/a
>
<
a
class
=
"
{{previous_classname}}
"
data
-
i18n
=
"
Previous
"
href
=
"
{{previous_url}}
"
>
Previous
<
/a
>
<
a
class
=
"
{{next_classname}}
"
data
-
i18n
=
"
Next
"
href
=
"
{{next_url}}
"
>
Next
<
/a
>
<
a
class
=
"
{{next_classname}}
"
data
-
i18n
=
"
Next
"
href
=
"
{{next_url}}
"
>
Next
<
/a
>
<
span
class
=
"
ui-btn ui-disabled
"
data
-
i18n
=
"
{{record}}
"
>
{{
record
}}
<
/span
>
<
span
class
=
"
ui-disabled ui-right
"
data
-
i18n
=
"
{{record}}
"
>
{{
record
}}
<
/span
>
<
/div
>
<
/nav
>
</script>
</script>
<script
id=
"listbox-template"
type=
"text/x-handlebars-template"
>
<script
id=
"listbox-template"
type=
"text/x-handlebars-template"
>
...
...
bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_listbox_html.xml
View file @
d2f8c300
...
@@ -234,7 +234,7 @@
...
@@ -234,7 +234,7 @@
</item>
</item>
<item>
<item>
<key>
<string>
serial
</string>
</key>
<key>
<string>
serial
</string>
</key>
<value>
<string>
963.5
0750.47688.32426
</string>
</value>
<value>
<string>
963.5
2015.15055.51592
</string>
</value>
</item>
</item>
<item>
<item>
<key>
<string>
state
</string>
</key>
<key>
<string>
state
</string>
</key>
...
@@ -252,7 +252,7 @@
...
@@ -252,7 +252,7 @@
</tuple>
</tuple>
<state>
<state>
<tuple>
<tuple>
<float>
151
1952124.83
</float>
<float>
151
2039069.26
</float>
<string>
UTC
</string>
<string>
UTC
</string>
</tuple>
</tuple>
</state>
</state>
...
...
bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_listbox_js.js
View file @
d2f8c300
...
@@ -42,20 +42,15 @@
...
@@ -42,20 +42,15 @@
loading_class_list
=
[
'
ui-icon-spinner
'
,
'
ui-btn-icon-left
'
],
loading_class_list
=
[
'
ui-icon-spinner
'
,
'
ui-btn-icon-left
'
],
disabled_class
=
'
ui-disabled
'
;
disabled_class
=
'
ui-disabled
'
;
function
renderSubField
(
gadget
,
element
,
sub_field_json
)
{
function
renderEditableField
(
gadget
,
element
,
column_list
,
field_table
)
{
sub_field_json
.
editable
=
sub_field_json
.
editable
&&
gadget
.
state
.
editable
;
var
i
,
return
gadget
.
declareGadget
(
promise_list
=
[],
'
gadget_erp5_label_field.html
'
,
uid_value_dict
=
{},
{
uid_value
,
element
:
element
,
column
,
scope
:
sub_field_json
.
key
line
,
}
element_list
=
element
.
querySelectorAll
(
"
.editable_div
"
);
)
gadget
.
props
.
listbox_uid_dict
=
{};
gadget
.
props
.
cell_gadget_list
=
[];
function
renderSubCell
(
element
,
sub_field_json
)
{
sub_field_json
.
editable
=
sub_field_json
.
editable
&&
gadget
.
state
.
editable
;
// XXX
return
gadget
.
declareGadget
(
'
gadget_erp5_label_field.html
'
,
{
element
:
element
,
scope
:
sub_field_json
.
key
})
.
push
(
function
(
cell_gadget
)
{
.
push
(
function
(
cell_gadget
)
{
gadget
.
props
.
cell_gadget_list
.
push
(
cell_gadget
);
gadget
.
props
.
cell_gadget_list
.
push
(
cell_gadget
);
return
cell_gadget
.
render
({
return
cell_gadget
.
render
({
...
@@ -65,23 +60,23 @@
...
@@ -65,23 +60,23 @@
});
});
});
});
}
}
function
renderEditableField
(
gadget
,
element
,
column_list
,
field_table
)
{
var
i
,
promise_list
=
[],
column
,
line
,
element_list
=
element
.
querySelectorAll
(
"
.editable_div
"
);
for
(
i
=
0
;
i
<
element_list
.
length
;
i
+=
1
)
{
for
(
i
=
0
;
i
<
element_list
.
length
;
i
+=
1
)
{
column
=
element_list
[
i
].
getAttribute
(
"
data-column
"
);
column
=
element_list
[
i
].
getAttribute
(
"
data-column
"
);
line
=
element_list
[
i
].
getAttribute
(
"
data-line
"
);
line
=
element_list
[
i
].
getAttribute
(
"
data-line
"
);
if
(
gadget
.
props
.
listbox_uid_dict
.
key
===
undefined
)
{
gadget
.
props
.
listbox_uid_dict
.
key
=
gadget
.
state
.
allDocs_result
.
data
.
rows
[
line
].
value
[
"
listbox_uid:list
"
].
key
;
promise_list
.
push
(
renderSubField
(
gadget
.
props
.
listbox_uid_dict
.
value
=
[
gadget
.
state
.
allDocs_result
.
data
.
rows
[
line
].
value
[
"
listbox_uid:list
"
].
value
];
gadget
,
uid_value_dict
[
gadget
.
state
.
allDocs_result
.
data
.
rows
[
line
].
value
[
"
listbox_uid:list
"
].
value
]
=
null
;
}
else
{
uid_value
=
gadget
.
state
.
allDocs_result
.
data
.
rows
[
line
].
value
[
"
listbox_uid:list
"
].
value
;
if
(
!
uid_value_dict
.
hasOwnProperty
(
uid_value
))
{
uid_value_dict
[
uid_value
]
=
null
;
gadget
.
props
.
listbox_uid_dict
.
value
.
push
(
uid_value
);
}
}
promise_list
.
push
(
renderSubCell
(
element_list
[
i
],
element_list
[
i
],
field_table
[
line
].
cell_list
[
column
]
||
""
));
field_table
[
line
].
cell_list
[
column
]
||
""
));
}
}
return
RSVP
.
all
(
promise_list
);
return
RSVP
.
all
(
promise_list
);
}
}
...
@@ -104,9 +99,9 @@
...
@@ -104,9 +99,9 @@
"
column_list
"
:
column_list
"
column_list
"
:
column_list
}
}
))
))
.
push
(
function
(
my
_html
)
{
.
push
(
function
(
table_part
_html
)
{
container
=
document
.
createElement
(
container_name
);
container
=
document
.
createElement
(
container_name
);
container
.
innerHTML
=
my
_html
;
container
.
innerHTML
=
table_part
_html
;
return
renderEditableField
(
gadget
,
container
,
column_list
,
row_list
);
return
renderEditableField
(
gadget
,
container
,
column_list
,
row_list
);
})
})
.
push
(
function
()
{
.
push
(
function
()
{
...
@@ -122,8 +117,8 @@
...
@@ -122,8 +117,8 @@
}
}
function
renderListboxTfoot
(
gadget
,
nav
,
foot
_sum
)
{
function
renderListboxTfoot
(
gadget
,
nav
,
foot
)
{
return
renderTablePart
(
gadget
,
listbox_tfoot_template
,
foot
_sum
,
"
tfoot
"
)
return
renderTablePart
(
gadget
,
listbox_tfoot_template
,
foot
,
"
tfoot
"
)
.
push
(
function
()
{
.
push
(
function
()
{
return
gadget
.
translateHtml
(
listbox_nav_template
(
return
gadget
.
translateHtml
(
listbox_nav_template
(
{
{
...
@@ -153,7 +148,10 @@
...
@@ -153,7 +148,10 @@
// Init local properties
// Init local properties
.
ready
(
function
()
{
.
ready
(
function
()
{
this
.
props
=
{
this
.
props
=
{
// holds references to all editable sub-fields
cell_gadget_list
:
[],
cell_gadget_list
:
[],
// ERP5 needs listbox_uid:list with UIDs of editable sub-documents
// so it can search for them in REQUEST.form under <field.id>_<sub-document.uid>
listbox_uid_dict
:
{}
listbox_uid_dict
:
{}
};
};
})
})
...
@@ -194,7 +192,7 @@
...
@@ -194,7 +192,7 @@
}
}
/** Check whether item is in outer-scoped field_json.column_list */
/** Check whether item is in outer-scoped field_json.column_list */
function
is
_in_column_l
ist
(
item
)
{
function
is
InColumnL
ist
(
item
)
{
for
(
i
=
0
;
i
<
field_json
.
column_list
.
length
;
i
+=
1
)
{
for
(
i
=
0
;
i
<
field_json
.
column_list
.
length
;
i
+=
1
)
{
if
(
field_json
.
column_list
[
i
][
0
]
===
item
[
0
]
&&
field_json
.
column_list
[
i
][
1
]
===
item
[
1
])
{
if
(
field_json
.
column_list
[
i
][
0
]
===
item
[
0
]
&&
field_json
.
column_list
[
i
][
1
]
===
item
[
1
])
{
return
true
;
return
true
;
...
@@ -205,12 +203,12 @@
...
@@ -205,12 +203,12 @@
// use only visible columns for sort
// use only visible columns for sort
if
(
field_json
.
sort_column_list
.
length
)
{
if
(
field_json
.
sort_column_list
.
length
)
{
sort_column_list
=
field_json
.
sort_column_list
.
filter
(
is
_in_column_l
ist
);
sort_column_list
=
field_json
.
sort_column_list
.
filter
(
is
InColumnL
ist
);
}
}
// use only visible columns for search
// use only visible columns for search
if
(
field_json
.
search_column_list
.
length
)
{
if
(
field_json
.
search_column_list
.
length
)
{
search_column_list
=
field_json
.
search_column_list
.
filter
(
is
_in_column_l
ist
);
search_column_list
=
field_json
.
search_column_list
.
filter
(
is
InColumnL
ist
);
}
}
search_column_list
.
push
([
"
searchable_text
"
,
"
Searchable Text
"
]);
search_column_list
.
push
([
"
searchable_text
"
,
"
Searchable Text
"
]);
...
@@ -458,7 +456,7 @@
...
@@ -458,7 +456,7 @@
counter
=
Math
.
min
(
allDocs_result
.
data
.
total_rows
,
lines
);
counter
=
Math
.
min
(
allDocs_result
.
data
.
total_rows
,
lines
);
}
}
sort_list
=
JSON
.
parse
(
gadget
.
state
.
sort_list_json
);
sort_list
=
JSON
.
parse
(
gadget
.
state
.
sort_list_json
);
// Every line points to a sub-document so we need those links
for
(
i
=
0
;
i
<
counter
;
i
+=
1
)
{
for
(
i
=
0
;
i
<
counter
;
i
+=
1
)
{
promise_list
.
push
(
promise_list
.
push
(
gadget
.
getUrlFor
({
gadget
.
getUrlFor
({
...
@@ -479,33 +477,51 @@
...
@@ -479,33 +477,51 @@
return
RSVP
.
all
(
promise_list
);
return
RSVP
.
all
(
promise_list
);
})
})
.
push
(
function
(
result
_list
)
{
.
push
(
function
(
line_link
_list
)
{
var
row_list
=
[],
var
row_list
=
[],
value
,
value
,
cell_list
,
cell_list
,
tmp_url
,
listbox_tbody_template
;
listbox_tbody_template
;
// reset list of UIDs of editable sub-documents
gadget
.
props
.
listbox_uid_dict
=
{
key
:
undefined
,
value
:
[]
};
// clear list of previous sub-gadgets
gadget
.
props
.
cell_gadget_list
=
[];
for
(
i
=
0
;
i
<
counter
;
i
+=
1
)
{
for
(
i
=
0
;
i
<
counter
;
i
+=
1
)
{
tmp_url
=
result_list
[
i
];
cell_list
=
[];
cell_list
=
[];
for
(
j
=
0
;
j
<
column_list
.
length
;
j
+=
1
)
{
for
(
j
=
0
;
j
<
column_list
.
length
;
j
+=
1
)
{
value
=
allDocs_result
.
data
.
rows
[
i
].
value
[
column_list
[
j
][
0
]]
||
""
;
value
=
allDocs_result
.
data
.
rows
[
i
].
value
[
column_list
[
j
][
0
]]
||
""
;
// value can be simple string with value in case of non-editable field
// thus we construct basic "field_json" manually and insert the value in "default"
if
(
typeof
value
===
"
string
"
)
{
if
(
typeof
value
===
"
string
"
)
{
value
=
{
value
=
{
'
editable
'
:
0
,
'
editable
'
:
0
,
'
default
'
:
value
'
default
'
:
value
};
};
}
}
value
.
href
=
tmp_url
;
value
.
href
=
line_link_list
[
i
]
;
value
.
editable
=
value
.
editable
&&
gadget
.
state
.
editable
;
value
.
editable
=
value
.
editable
&&
gadget
.
state
.
editable
;
value
.
line
=
i
;
value
.
line
=
i
;
value
.
column
=
j
;
value
.
column
=
j
;
cell_list
.
push
(
value
);
cell_list
.
push
(
value
);
}
}
// note row's editable UID into gadget.props.listbox_uid_dict if exists to send it back to ERP5
// together with ListBox data. The listbox_uid_dict has quite surprising structure {key: <key>, value: <uid-array>}
if
(
allDocs_result
.
data
.
rows
[
i
].
value
[
'
listbox_uid:list
'
]
!==
undefined
)
{
gadget
.
props
.
listbox_uid_dict
.
key
=
allDocs_result
.
data
.
rows
[
i
].
value
[
'
listbox_uid:list
'
].
key
;
gadget
.
props
.
listbox_uid_dict
.
value
.
push
(
allDocs_result
.
data
.
rows
[
i
].
value
[
'
listbox_uid:list
'
].
value
);
// we could come up with better name than "value" for almost everything ^^
}
else
{
// if the document does not have listbox_uid:list then no gadget should be editable
cell_list
.
forEach
(
function
(
cell
)
{
cell
.
editable
=
false
;
});
}
row_list
.
push
({
row_list
.
push
({
"
value
"
:
allDocs_result
.
data
.
rows
[
i
].
value
.
uid
,
"
uid
"
:
allDocs_result
.
data
.
rows
[
i
].
value
.
uid
,
"
jump
"
:
tmp_url
,
"
jump
"
:
line_link_list
[
i
]
,
"
cell_list
"
:
cell_list
,
"
cell_list
"
:
cell_list
,
"
line_icon
"
:
gadget
.
state
.
line_icon
"
line_icon
"
:
gadget
.
state
.
line_icon
});
});
...
@@ -517,7 +533,7 @@
...
@@ -517,7 +533,7 @@
listbox_tbody_template
=
listbox_hidden_tbody_template
;
listbox_tbody_template
=
listbox_hidden_tbody_template
;
}
}
return
renderTablePart
(
gadget
,
listbox_tbody_template
,
row_list
,
"
tbody
"
,
"
tbody
"
);
return
renderTablePart
(
gadget
,
listbox_tbody_template
,
row_list
,
"
tbody
"
);
})
})
.
push
(
function
()
{
.
push
(
function
()
{
var
prev_param
=
{},
var
prev_param
=
{},
...
@@ -541,48 +557,50 @@
...
@@ -541,48 +557,50 @@
})
})
.
push
(
function
(
url_list
)
{
.
push
(
function
(
url_list
)
{
var
summary
=
gadget
.
state
.
allDocs_result
.
sum
||
[],
// render summary footer if available
var
result_sum
=
(
gadget
.
state
.
allDocs_result
.
sum
||
{}).
rows
||
[],
// render summary footer if available
tfoot_sum
=
summary
.
map
(
function
(
row
,
row_index
)
{
summary
=
result_sum
.
map
(
function
(
row
,
row_index
)
{
var
row_editability
=
row
[
'
listbox_uid:list
'
]
!==
undefined
;
return
{
return
{
"
value
"
:
'
summary
'
+
row_index
,
"
uid
"
:
'
summary
'
+
row_index
,
"
cell_list
"
:
column_list
.
map
(
function
(
col_name
,
col_index
)
{
"
cell_list
"
:
column_list
.
map
(
function
(
col_name
,
col_index
)
{
var
field_json
=
row
[
col_name
[
0
]]
||
""
;
var
field_json
=
row
.
value
[
col_name
[
0
]]
||
""
;
if
(
typeof
field_json
==
"
string
"
)
{
if
(
typeof
field_json
==
=
"
string
"
)
{
field_json
=
{
'
default
'
:
'
value
'
,
'
editable
'
:
0
};
field_json
=
{
'
default
'
:
'
value
'
,
'
editable
'
:
0
};
}
}
field_json
.
editable
=
field_json
.
editable
&&
row_editability
;
field_json
.
column
=
col_index
;
field_json
.
column
=
col_index
;
field_json
.
line
=
row_index
;
field_json
.
line
=
row_index
;
return
field_json
;
return
field_json
;
})
})
};
};
}),
}),
tfoot_count
=
{
navigation
=
{
"
previous_url
"
:
url_list
[
0
],
"
previous_url
"
:
url_list
[
0
],
"
next_url
"
:
url_list
[
1
],
"
next_url
"
:
url_list
[
1
],
"
previous_classname
"
:
"
ui-btn ui-icon-carat-l ui-btn-icon-left responsive ui-first-child
"
,
"
previous_classname
"
:
"
ui-btn ui-icon-carat-l ui-btn-icon-left responsive ui-first-child
"
,
"
next_classname
"
:
"
ui-btn ui-icon-carat-r ui-btn-icon-right responsive ui-last-child
"
"
next_classname
"
:
"
ui-btn ui-icon-carat-r ui-btn-icon-right responsive ui-last-child
"
};
};
tfoot_count
.
colspan
=
column_list
.
length
+
gadget
.
state
.
show_anchor
+
navigation
.
colspan
=
column_list
.
length
+
gadget
.
state
.
show_anchor
+
(
gadget
.
state
.
line_icon
?
1
:
0
);
(
gadget
.
state
.
line_icon
?
1
:
0
);
if
((
gadget
.
state
.
begin_from
===
0
)
&&
(
counter
===
0
))
{
if
((
gadget
.
state
.
begin_from
===
0
)
&&
(
counter
===
0
))
{
tfoot_count
.
record
=
variable
.
translated_no_record
;
navigation
.
record
=
variable
.
translated_no_record
;
}
else
if
((
allDocs_result
.
data
.
rows
.
length
<=
lines
)
&&
(
gadget
.
state
.
begin_from
===
0
))
{
}
else
if
((
allDocs_result
.
data
.
rows
.
length
<=
lines
)
&&
(
gadget
.
state
.
begin_from
===
0
))
{
tfoot_count
.
record
=
counter
+
"
"
+
variable
.
translated_records
;
navigation
.
record
=
counter
+
"
"
+
variable
.
translated_records
;
}
else
{
}
else
{
tfoot_count
.
record
=
variable
.
translated_records
+
"
"
+
(((
gadget
.
state
.
begin_from
+
lines
)
/
lines
-
1
)
*
lines
+
1
)
+
"
-
"
+
(((
gadget
.
state
.
begin_from
+
lines
)
/
lines
-
1
)
*
lines
+
counter
);
navigation
.
record
=
variable
.
translated_records
+
"
"
+
(((
gadget
.
state
.
begin_from
+
lines
)
/
lines
-
1
)
*
lines
+
1
)
+
"
-
"
+
(((
gadget
.
state
.
begin_from
+
lines
)
/
lines
-
1
)
*
lines
+
counter
);
}
}
if
(
gadget
.
state
.
begin_from
===
0
)
{
if
(
gadget
.
state
.
begin_from
===
0
)
{
tfoot_count
.
previous_classname
+=
"
ui-disabled
"
;
navigation
.
previous_classname
+=
"
ui-disabled
"
;
}
}
if
(
allDocs_result
.
data
.
rows
.
length
<=
lines
)
{
if
(
allDocs_result
.
data
.
rows
.
length
<=
lines
)
{
tfoot_count
.
next_classname
+=
"
ui-disabled
"
;
navigation
.
next_classname
+=
"
ui-disabled
"
;
}
}
return
renderListboxTfoot
(
gadget
,
tfoot_count
,
tfoot_sum
);
return
renderListboxTfoot
(
gadget
,
navigation
,
summary
);
})
})
.
push
(
function
(
my_html
)
{
.
push
(
function
()
{
var
loading_element_classList
=
gadget
.
element
.
querySelector
(
"
.listboxloader
"
).
classList
;
var
loading_element_classList
=
gadget
.
element
.
querySelector
(
"
.listboxloader
"
).
classList
;
loading_element_classList
.
remove
.
apply
(
loading_element_classList
,
loading_class_list
);
loading_element_classList
.
remove
.
apply
(
loading_element_classList
,
loading_class_list
);
});
});
...
@@ -662,7 +680,7 @@
...
@@ -662,7 +680,7 @@
},
function
(
error
)
{
},
function
(
error
)
{
// do not crash interface if allDocs fails
// do not crash interface if allDocs fails
//this will catch all error, not only search criteria invalid error
//
this will catch all error, not only search criteria invalid error
if
(
error
instanceof
RSVP
.
CancellationError
)
{
if
(
error
instanceof
RSVP
.
CancellationError
)
{
throw
error
;
throw
error
;
}
}
...
@@ -674,10 +692,10 @@
...
@@ -674,10 +692,10 @@
})
})
.
declareMethod
(
"
getContent
"
,
function
(
options
)
{
.
declareMethod
(
"
getContent
"
,
function
(
options
)
{
var
form_
gadget
=
this
,
var
gadget
=
this
,
k
,
k
,
field
_gadget
,
sub
_gadget
,
count
=
form_
gadget
.
props
.
cell_gadget_list
.
length
,
count
=
gadget
.
props
.
cell_gadget_list
.
length
,
data
=
{},
data
=
{},
queue
=
new
RSVP
.
Queue
();
queue
=
new
RSVP
.
Queue
();
...
@@ -691,17 +709,18 @@
...
@@ -691,17 +709,18 @@
}
}
for
(
k
=
0
;
k
<
count
;
k
+=
1
)
{
for
(
k
=
0
;
k
<
count
;
k
+=
1
)
{
field_gadget
=
form_
gadget
.
props
.
cell_gadget_list
[
k
];
sub_gadget
=
gadget
.
props
.
cell_gadget_list
[
k
];
// XXX Hack until better defined
// XXX Hack until better defined
if
(
field
_gadget
.
getContent
!==
undefined
)
{
if
(
sub
_gadget
.
getContent
!==
undefined
)
{
queue
queue
.
push
(
field_gadget
.
getContent
.
bind
(
field
_gadget
,
options
))
.
push
(
sub_gadget
.
getContent
.
bind
(
sub
_gadget
,
options
))
.
push
(
extendData
);
.
push
(
extendData
);
}
}
}
}
return
queue
return
queue
.
push
(
function
()
{
.
push
(
function
()
{
data
[
form_gadget
.
props
.
listbox_uid_dict
.
key
]
=
form_gadget
.
props
.
listbox_uid_dict
.
value
;
// gadget.props.listbox_uid_dict.value is an array of UIDs of all editable documents
data
[
gadget
.
props
.
listbox_uid_dict
.
key
]
=
gadget
.
props
.
listbox_uid_dict
.
value
;
return
data
;
return
data
;
});
});
})
})
...
...
bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_listbox_js.xml
View file @
d2f8c300
...
@@ -236,7 +236,7 @@
...
@@ -236,7 +236,7 @@
</item>
</item>
<item>
<item>
<key>
<string>
serial
</string>
</key>
<key>
<string>
serial
</string>
</key>
<value>
<string>
963.
50757.35572.58794
</string>
</value>
<value>
<string>
963.
60288.35957.62805
</string>
</value>
</item>
</item>
<item>
<item>
<key>
<string>
state
</string>
</key>
<key>
<string>
state
</string>
</key>
...
@@ -254,7 +254,7 @@
...
@@ -254,7 +254,7 @@
</tuple>
</tuple>
<state>
<state>
<tuple>
<tuple>
<float>
151
1952430.52
</float>
<float>
151
2439237.91
</float>
<string>
UTC
</string>
<string>
UTC
</string>
</tuple>
</tuple>
</state>
</state>
...
...
bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_nojqm_css.css
View file @
d2f8c300
...
@@ -1221,6 +1221,9 @@ div[data-gadget-scope='erp5_searchfield'] .ui-input-text div[data-gadget-scope='
...
@@ -1221,6 +1221,9 @@ div[data-gadget-scope='erp5_searchfield'] .ui-input-text div[data-gadget-scope='
div
[
data-gadget-scope
=
'erp5_searchfield'
]
button
{
div
[
data-gadget-scope
=
'erp5_searchfield'
]
button
{
padding
:
3pt
;
padding
:
3pt
;
}
}
.document_table
{
/* end-of table */
}
.document_table
.ui-table-header
{
.document_table
.ui-table-header
{
display
:
flex
;
display
:
flex
;
padding-bottom
:
6pt
;
padding-bottom
:
6pt
;
...
@@ -1264,24 +1267,30 @@ div[data-gadget-scope='erp5_searchfield'] button {
...
@@ -1264,24 +1267,30 @@ div[data-gadget-scope='erp5_searchfield'] button {
.document_table
table
{
.document_table
table
{
width
:
100%
;
width
:
100%
;
text-align
:
left
;
text-align
:
left
;
/* end-of tbody, tfoot*/
}
}
.document_table
table
th
,
.document_table
table
th
,
.document_table
table
td
{
.document_table
table
td
{
vertical-align
:
middle
;
vertical-align
:
middle
;
padding
:
3pt
;
}
}
.document_table
table
thead
{
.document_table
table
thead
,
.document_table
table
tfoot
{
background-color
:
#0E81C2
;
background-color
:
#0E81C2
;
color
:
#FFFFFF
;
color
:
#FFFFFF
;
}
}
.document_table
table
thead
a
{
.document_table
table
thead
a
,
.document_table
table
tfoot
a
{
color
:
#FFFFFF
;
color
:
#FFFFFF
;
text-decoration
:
underline
;
text-decoration
:
underline
;
}
}
.document_table
table
thead
tr
th
{
.document_table
table
thead
tr
th
,
.document_table
table
tfoot
tr
th
{
padding
:
6pt
3pt
;
padding
:
6pt
3pt
;
}
}
@media
not
screen
and
(
min-width
:
45em
)
{
@media
not
screen
and
(
min-width
:
45em
)
{
.document_table
table
thead
{
.document_table
table
thead
,
.document_table
table
tfoot
{
display
:
none
;
display
:
none
;
}
}
}
}
...
@@ -1301,7 +1310,6 @@ div[data-gadget-scope='erp5_searchfield'] button {
...
@@ -1301,7 +1310,6 @@ div[data-gadget-scope='erp5_searchfield'] button {
@media
not
screen
and
(
max-width
:
85em
),
only
screen
and
(
min-width
:
45em
)
and
(
max-width
:
85em
)
{
@media
not
screen
and
(
max-width
:
85em
),
only
screen
and
(
min-width
:
45em
)
and
(
max-width
:
85em
)
{
.document_table
table
tbody
a
{
.document_table
table
tbody
a
{
display
:
block
;
display
:
block
;
padding
:
3pt
;
}
}
}
}
@media
not
screen
and
(
min-width
:
45em
)
{
@media
not
screen
and
(
min-width
:
45em
)
{
...
@@ -1370,41 +1378,42 @@ div[data-gadget-scope='erp5_searchfield'] button {
...
@@ -1370,41 +1378,42 @@ div[data-gadget-scope='erp5_searchfield'] button {
content
:
" ~ "
;
content
:
" ~ "
;
}
}
}
}
.document_table
table
tfoot
.ui-controlgroup-controls
{
.document_table
nav
{
display
:
flex
;
display
:
flex
;
padding-top
:
6pt
;
padding-top
:
6pt
;
border-top
:
2px
solid
rgba
(
0
,
0
,
0
,
0.14902
);
border-top
:
2px
solid
rgba
(
0
,
0
,
0
,
0.14902
);
}
}
.document_table
table
tfoot
.ui-controlgroup-controls
span
{
.document_table
nav
span
{
opacity
:
.3
;
opacity
:
.3
;
flex
:
2
;
flex
:
2
;
text-align
:
right
;
text-align
:
right
;
float
:
right
;
}
}
.document_table
table
tfoot
.ui-controlgroup-controls
a
{
.document_table
nav
a
{
padding
:
6pt
;
padding
:
6pt
;
border
:
1px
solid
rgba
(
0
,
0
,
0
,
0.14
);
border
:
1px
solid
rgba
(
0
,
0
,
0
,
0.14
);
border-radius
:
0.325em
;
border-radius
:
0.325em
;
margin-right
:
6pt
;
margin-right
:
6pt
;
}
}
.document_table
table
tfoot
.ui-controlgroup-controls
a
:last-of-type
{
.document_table
nav
a
:last-of-type
{
margin-right
:
0
;
margin-right
:
0
;
}
}
.document_table
table
tfoot
.ui-controlgroup-controls
a
:hover
,
.document_table
nav
a
:hover
,
.document_table
table
tfoot
.ui-controlgroup-controls
a
:active
{
.document_table
nav
a
:active
{
background-color
:
#e0e0e0
;
background-color
:
#e0e0e0
;
}
}
@media
not
screen
and
(
min-width
:
45em
)
{
@media
not
screen
and
(
min-width
:
45em
)
{
.document_table
table
tfoot
.ui-controlgroup-controls
a
{
.document_table
nav
a
{
overflow
:
hidden
;
overflow
:
hidden
;
text-indent
:
-9999px
;
text-indent
:
-9999px
;
white-space
:
nowrap
;
white-space
:
nowrap
;
}
}
}
}
.document_table
table
tfoot
.ui-controlgroup-controls
a
::before
{
.document_table
nav
a
::before
{
margin-right
:
6pt
;
margin-right
:
6pt
;
}
}
@media
not
screen
and
(
min-width
:
45em
)
{
@media
not
screen
and
(
min-width
:
45em
)
{
.document_table
table
tfoot
.ui-controlgroup-controls
a
::before
{
.document_table
nav
a
::before
{
float
:
left
;
float
:
left
;
text-indent
:
6pt
;
text-indent
:
6pt
;
}
}
...
...
bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_nojqm_css.xml
View file @
d2f8c300
...
@@ -242,7 +242,7 @@
...
@@ -242,7 +242,7 @@
</item>
</item>
<item>
<item>
<key>
<string>
serial
</string>
</key>
<key>
<string>
serial
</string>
</key>
<value>
<string>
96
2.1204.63259.57958
</string>
</value>
<value>
<string>
96
3.54869.55137.61115
</string>
</value>
</item>
</item>
<item>
<item>
<key>
<string>
state
</string>
</key>
<key>
<string>
state
</string>
</key>
...
@@ -260,7 +260,7 @@
...
@@ -260,7 +260,7 @@
</tuple>
</tuple>
<state>
<state>
<tuple>
<tuple>
<float>
15
05133981.01
</float>
<float>
15
12455490.33
</float>
<string>
UTC
</string>
<string>
UTC
</string>
</tuple>
</tuple>
</state>
</state>
...
...
bt5/erp5_web_renderjs_ui/SkinTemplateItem/portal_skins/erp5_web_renderjs_ui/erp5css.less.txt
View file @
d2f8c300
...
@@ -1458,9 +1458,10 @@ div[data-gadget-scope='erp5_searchfield'] {
...
@@ -1458,9 +1458,10 @@ div[data-gadget-scope='erp5_searchfield'] {
th, td {
th, td {
// line-height: 1.5em;
// line-height: 1.5em;
vertical-align: middle;
vertical-align: middle;
padding: @half-margin-size;
}
}
thead {
thead
, tfoot
{
background-color: @colorsubheaderbackground;
background-color: @colorsubheaderbackground;
color: @white;
color: @white;
...
@@ -1500,7 +1501,6 @@ div[data-gadget-scope='erp5_searchfield'] {
...
@@ -1500,7 +1501,6 @@ div[data-gadget-scope='erp5_searchfield'] {
@media @desktop, @tablet {
@media @desktop, @tablet {
a {
a {
display: block;
display: block;
padding: @half-margin-size;
}
}
}
}
...
@@ -1580,10 +1580,10 @@ div[data-gadget-scope='erp5_searchfield'] {
...
@@ -1580,10 +1580,10 @@ div[data-gadget-scope='erp5_searchfield'] {
}
}
}
}
}
}
}
}
/* end-of tbody, tfoot*/
} /* end-of table */
tfoot .ui-controlgroup-controls
{
nav
{
display: flex;
display: flex;
padding-top: @margin-size;
padding-top: @margin-size;
border-top: 2px solid rgba(0, 0, 0, 0.14902);
border-top: 2px solid rgba(0, 0, 0, 0.14902);
...
@@ -1592,6 +1592,7 @@ div[data-gadget-scope='erp5_searchfield'] {
...
@@ -1592,6 +1592,7 @@ div[data-gadget-scope='erp5_searchfield'] {
opacity: .3;
opacity: .3;
flex: 2;
flex: 2;
text-align: right;
text-align: right;
float: right;
}
}
a {
a {
padding: @margin-size;
padding: @margin-size;
...
@@ -1621,8 +1622,6 @@ div[data-gadget-scope='erp5_searchfield'] {
...
@@ -1621,8 +1622,6 @@ div[data-gadget-scope='erp5_searchfield'] {
}
}
}
}
}
}
}
}
}
/**********************************************
/**********************************************
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment