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
Aurélien Vermylen
erp5
Commits
dfb62b97
Commit
dfb62b97
authored
Dec 12, 2017
by
Tomáš Peterka
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[hal_json+renderjs] Implement "stat" line for ListBox
parent
f4eb48d9
Changes
18
Hide whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
773 additions
and
193 deletions
+773
-193
bt5/erp5_hal_json_style/SkinTemplateItem/portal_skins/erp5_hal_json_style/ERP5Document_getHateoas.py
...rtal_skins/erp5_hal_json_style/ERP5Document_getHateoas.py
+66
-2
bt5/erp5_ui_test/SkinTemplateItem/portal_skins/erp5_ui_test/FooModule_statMethod.py
...ateItem/portal_skins/erp5_ui_test/FooModule_statMethod.py
+12
-0
bt5/erp5_ui_test/SkinTemplateItem/portal_skins/erp5_ui_test/FooModule_statMethod.xml
...teItem/portal_skins/erp5_ui_test/FooModule_statMethod.xml
+66
-0
bt5/erp5_ui_test/SkinTemplateItem/portal_skins/erp5_ui_test/FooModule_statQuantity.py
...eItem/portal_skins/erp5_ui_test/FooModule_statQuantity.py
+6
-0
bt5/erp5_ui_test/SkinTemplateItem/portal_skins/erp5_ui_test/FooModule_statQuantity.xml
...Item/portal_skins/erp5_ui_test/FooModule_statQuantity.xml
+66
-0
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
+26
-20
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
+37
-18
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
+172
-99
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
+20
-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
bt5/erp5_web_renderjs_ui_test/PathTemplateItem/portal_tests/renderjs_ui_listbox_zuite/testStatColumns.xml
...ortal_tests/renderjs_ui_listbox_zuite/testStatColumns.xml
+58
-0
bt5/erp5_web_renderjs_ui_test/PathTemplateItem/portal_tests/renderjs_ui_listbox_zuite/testStatColumns.zpt
...ortal_tests/renderjs_ui_listbox_zuite/testStatColumns.zpt
+73
-0
bt5/erp5_web_renderjs_ui_test/PathTemplateItem/portal_tests/renderjs_ui_listbox_zuite/testStatMethod.xml
...portal_tests/renderjs_ui_listbox_zuite/testStatMethod.xml
+58
-0
bt5/erp5_web_renderjs_ui_test/PathTemplateItem/portal_tests/renderjs_ui_listbox_zuite/testStatMethod.zpt
...portal_tests/renderjs_ui_listbox_zuite/testStatMethod.zpt
+74
-0
No files found.
bt5/erp5_hal_json_style/SkinTemplateItem/portal_skins/erp5_hal_json_style/ERP5Document_getHateoas.py
View file @
dfb62b97
...
...
@@ -46,10 +46,26 @@ MARKER = []
if
REQUEST
is
None
:
REQUEST
=
context
.
REQUEST
# raise Unauthorized
if
response
is
None
:
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
def
byteify
(
string
):
if
isinstance
(
string
,
dict
):
...
...
@@ -669,6 +685,8 @@ def renderField(traversed_document, field, form, value=None, meta_type=None, key
"lines"
:
lines
,
"default_params"
:
default_params
,
"list_method"
:
list_method_name
,
"show_stat"
:
field
.
get_value
(
'stat_method'
)
!=
""
or
len
(
field
.
get_value
(
'stat_columns'
))
>
0
,
"show_count"
:
field
.
get_value
(
'count_method'
)
!=
""
,
"query"
:
url_template_dict
[
"jio_search_template"
]
%
{
"query"
:
make_query
({
"query"
:
sql_catalog
.
buildQuery
(
...
...
@@ -1456,8 +1474,54 @@ def calculateHateoas(is_portal=None, is_site_root=None, traversed_document=None,
contents_item
[
select
]
=
getAttrFromAnything
(
search_result
,
select
,
property_getter
,
property_hasser
,
{
'brain'
:
search_result
})
# endfor select
contents_list
.
append
(
contents_item
)
result_dict
[
'_embedded'
][
'contents'
]
=
contents_list
result_dict
[
'_embedded'
][
'contents'
]
=
ensureSerializable
(
contents_list
)
# Compute statistics if the search issuer was ListBox
# or in future if the stats (SUM) are required by JIO call
source_field_meta_type
=
source_field
.
meta_type
if
source_field
is
not
None
else
""
if
source_field_meta_type
==
"ProxyField"
:
source_field_meta_type
=
source_field
.
getRecursiveTemplateField
().
meta_type
if
source_field
is
not
None
and
source_field_meta_type
==
"ListBox"
:
contents_stat_list
=
[]
# in case the search was issued by listbox we can provide results of
# stat_method and count_method back to the caller
# XXX: we should check whether they asked for it
stat_method
=
source_field
.
get_value
(
'stat_method'
)
stat_columns
=
source_field
.
get_value
(
'stat_columns'
)
# support only selection_name for stat methods because any `selection` is deprecated
# and should be removed
selection_name
=
source_field
.
get_value
(
'selection_name'
)
if
selection_name
and
'selection_name'
not
in
catalog_kw
:
catalog_kw
[
'selection_name'
]
=
selection_name
contents_stat
=
{}
if
len
(
stat_columns
)
>
0
:
# prefer stat per column (follow original ListBox.py implementation)
for
stat_name
,
stat_script
in
stat_columns
:
contents_stat
[
stat_name
]
=
getattr
(
traversed_document
,
stat_script
)(
**
catalog_kw
)
contents_stat_list
.
append
(
contents_stat
)
elif
stat_method
!=
""
and
stat_method
.
getMethodName
()
!=
list_method
:
# 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 (no "listbox_" prefix)
stat_method_result
=
getattr
(
traversed_document
,
stat_method
.
getMethodName
())(
**
catalog_kw
)
# stat method can return simple dictionary or subscriptable object thus we put it into one-item list
if
stat_method_result
is
not
None
and
not
isinstance
(
stat_method_result
,
(
list
,
tuple
)):
stat_method_result
=
[
stat_method_result
,
]
contents_stat_list
=
toBasicTypes
(
stat_method_result
)
or
[]
for
contents_stat
in
contents_stat_list
:
for
key
,
value
in
contents_stat
.
items
():
if
key
in
editable_field_dict
:
contents_stat
[
key
]
=
renderField
(
traversed_document
,
editable_field_dict
[
key
],
listbox_form
,
value
,
key
=
editable_field_dict
[
key
].
id
+
'__sum'
)
if
len
(
contents_stat_list
)
>
0
:
result_dict
[
'_embedded'
][
'sum'
]
=
ensureSerializable
(
contents_stat_list
)
# We should cleanup the selection if it exists in catalog params BUT
# we cannot because it requires escalated Permission.'modifyPortal' so
# the correct solution would be to ReportSection.popReport but unfortunately
# we don't have it anymore because we are asynchronous
return
result_dict
elif
mode
==
'form'
:
...
...
bt5/erp5_ui_test/SkinTemplateItem/portal_skins/erp5_ui_test/FooModule_statMethod.py
0 → 100644
View file @
dfb62b97
"""Compute stats from actual Foo Lines on a Foo object"""
column_list
=
[
'getQuantity'
,
'id'
]
result
=
{
c
:
0.0
for
c
in
column_list
}
for
line
in
context
.
contentValues
(
portal_type
=
"Foo"
):
for
column
in
column_list
:
value
=
getattr
(
line
,
column
)
if
callable
(
value
):
value
=
value
()
result
[
column
]
=
result
[
column
]
+
float
(
value
)
return
[
result
,
]
bt5/erp5_ui_test/SkinTemplateItem/portal_skins/erp5_ui_test/FooModule_statMethod.xml
0 → 100644
View file @
dfb62b97
<?xml version="1.0"?>
<ZopeData>
<record
id=
"1"
aka=
"AAAAAAAAAAE="
>
<pickle>
<global
name=
"Python Script"
module=
"erp5.portal_type"
/>
</pickle>
<pickle>
<dictionary>
<item>
<key>
<string>
Script_magic
</string>
</key>
<value>
<int>
3
</int>
</value>
</item>
<item>
<key>
<string>
_bind_names
</string>
</key>
<value>
<object>
<klass>
<global
name=
"NameAssignments"
module=
"Shared.DC.Scripts.Bindings"
/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key>
<string>
_asgns
</string>
</key>
<value>
<dictionary>
<item>
<key>
<string>
name_container
</string>
</key>
<value>
<string>
container
</string>
</value>
</item>
<item>
<key>
<string>
name_context
</string>
</key>
<value>
<string>
context
</string>
</value>
</item>
<item>
<key>
<string>
name_m_self
</string>
</key>
<value>
<string>
script
</string>
</value>
</item>
<item>
<key>
<string>
name_subpath
</string>
</key>
<value>
<string>
traverse_subpath
</string>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key>
<string>
_params
</string>
</key>
<value>
<string>
**kwargs
</string>
</value>
</item>
<item>
<key>
<string>
id
</string>
</key>
<value>
<string>
FooModule_statMethod
</string>
</value>
</item>
<item>
<key>
<string>
portal_type
</string>
</key>
<value>
<string>
Python Script
</string>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
bt5/erp5_ui_test/SkinTemplateItem/portal_skins/erp5_ui_test/FooModule_statQuantity.py
0 → 100644
View file @
dfb62b97
counter
=
0
for
value
in
context
.
contentValues
():
counter
=
counter
+
int
(
value
.
getQuantity
())
return
counter
bt5/erp5_ui_test/SkinTemplateItem/portal_skins/erp5_ui_test/FooModule_statQuantity.xml
0 → 100644
View file @
dfb62b97
<?xml version="1.0"?>
<ZopeData>
<record
id=
"1"
aka=
"AAAAAAAAAAE="
>
<pickle>
<global
name=
"Python Script"
module=
"erp5.portal_type"
/>
</pickle>
<pickle>
<dictionary>
<item>
<key>
<string>
Script_magic
</string>
</key>
<value>
<int>
3
</int>
</value>
</item>
<item>
<key>
<string>
_bind_names
</string>
</key>
<value>
<object>
<klass>
<global
name=
"NameAssignments"
module=
"Shared.DC.Scripts.Bindings"
/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key>
<string>
_asgns
</string>
</key>
<value>
<dictionary>
<item>
<key>
<string>
name_container
</string>
</key>
<value>
<string>
container
</string>
</value>
</item>
<item>
<key>
<string>
name_context
</string>
</key>
<value>
<string>
context
</string>
</value>
</item>
<item>
<key>
<string>
name_m_self
</string>
</key>
<value>
<string>
script
</string>
</value>
</item>
<item>
<key>
<string>
name_subpath
</string>
</key>
<value>
<string>
traverse_subpath
</string>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key>
<string>
_params
</string>
</key>
<value>
<string>
**kwargs
</string>
</value>
</item>
<item>
<key>
<string>
id
</string>
</key>
<value>
<string>
FooModule_statQuantity
</string>
</value>
</item>
<item>
<key>
<string>
portal_type
</string>
</key>
<value>
<string>
Python Script
</string>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_jio_js.js
View file @
dfb62b97
...
...
@@ -178,27 +178,33 @@
]
)
.
push
(
function
(
catalog_json
)
{
var
data
=
catalog_json
.
_embedded
.
contents
,
count
=
data
.
length
,
k
,
uri
,
item
,
result
=
[];
for
(
k
=
0
;
k
<
count
;
k
+=
1
)
{
item
=
data
[
k
];
uri
=
new
URI
(
item
.
_links
.
self
.
href
);
delete
item
.
_links
;
result
.
push
({
id
:
uri
.
segment
(
2
),
doc
:
{},
value
:
item
});
}
var
data
=
catalog_json
.
_embedded
.
contents
||
[],
summary
=
catalog_json
.
_embedded
.
sum
||
[],
count
=
catalog_json
.
_embedded
.
count
;
return
{
data
:
{
rows
:
result
,
total_rows
:
result
.
length
}
"
data
"
:
{
"
rows
"
:
data
.
map
(
function
(
item
)
{
var
uri
=
new
URI
(
item
.
_links
.
self
.
href
);
delete
item
.
_links
;
return
{
"
id
"
:
uri
.
segment
(
2
),
"
doc
"
:
{},
"
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
},
"
count
"
:
count
};
});
})
...
...
bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_jio_js.xml
View file @
dfb62b97
...
...
@@ -230,7 +230,7 @@
</item>
<item>
<key>
<string>
serial
</string>
</key>
<value>
<string>
9
47.45414.13002.1005
2
</string>
</value>
<value>
<string>
9
63.59331.40212.5543
2
</string>
</value>
</item>
<item>
<key>
<string>
state
</string>
</key>
...
...
@@ -248,7 +248,7 @@
</tuple>
<state>
<tuple>
<float>
1
449753994.81
</float>
<float>
1
512454358.33
</float>
<string>
UTC
</string>
</tuple>
</state>
...
...
bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_listbox_html.html
View file @
dfb62b97
...
...
@@ -45,14 +45,14 @@
<script
id=
"listbox-hidden-tbody-template"
type=
"text/x-handlebars-template"
>
<
table
>
<
tbody
class
=
"
tbody
"
>
{{
#
each
body_value
}}
{{
#
each
row_list
}}
<
tr
>
{{
#
if
..
/
show_anchor
}}
<
th
>
<
a
class
=
"
ui-link ui-btn ui-corner-all ui-icon-carat-r ui-btn-icon-notext
"
href
=
"
{{jump}}
"
><
/a
>
<
/th
>
{{
/
if
}}
{{
#
each
tr_value
}}
{{
#
each
cell_list
}}
<
td
>
{{
#
if
type
}}
{{
#
if
editable
}}
...
...
@@ -63,7 +63,7 @@
<
/a
>
{{
/
if
}}
{{
else
}}
<
a
href
=
"
{{href}}
"
class
=
"
ui-link
"
>
{{
tex
t
}}
<
/a
>
<
a
href
=
"
{{href}}
"
class
=
"
ui-link
"
>
{{
defaul
t
}}
<
/a
>
{{
/
if
}}
<
/td
>
{{
/
each
}}
...
...
@@ -82,7 +82,7 @@
<script
id=
"listbox-show-tbody-template"
type=
"text/x-handlebars-template"
>
<
table
>
<
tbody
class
=
"
tbody
"
>
{{
#
each
body_value
}}
{{
#
each
row_list
}}
<
tr
>
{{
#
if
..
/
show_anchor
}}
<
th
>
...
...
@@ -92,7 +92,7 @@
<
td
>
<
input
value
=
"
{{value}}
"
type
=
"
checkbox
"
checked
=
"
true
"
class
=
"
hide_element
"
>
<
/td
>
{{
#
each
tr_value
}}
{{
#
each
cell_list
}}
<
td
>
{{
#
if
type
}}
{{
#
if
editable
}}
...
...
@@ -103,7 +103,7 @@
<
/a
>
{{
/
if
}}
{{
else
}}
<
a
href
=
"
{{href}}
"
class
=
"
ui-link
"
>
{{
tex
t
}}
<
/a
>
<
a
href
=
"
{{href}}
"
class
=
"
ui-link
"
>
{{
defaul
t
}}
<
/a
>
{{
/
if
}}
<
/td
>
{{
/
each
}}
...
...
@@ -121,19 +121,38 @@
<script
id=
"listbox-tfoot-template"
type=
"text/x-handlebars-template"
>
<
table
>
<
tfoot
class
=
"
ui-bar-inherit tfoot
"
>
<
th
colspan
=
"
{{colspan}}
"
>
<
div
class
=
"
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
=
"
{{next_classname}}
"
data
-
i18n
=
"
Next
"
href
=
"
{{next_url}}
"
>
Next
<
/a
>
<
span
class
=
"
ui-btn ui-disabled
"
data
-
i18n
=
"
{{record}}
"
>
{{
record
}}
<
/span
>
<
/div
>
<
/div
>
<
/th
>
{{
#
each
row_list
}}
<
tr
>
{{
#
if
..
/
show_anchor
}}
<
td
>
Total
<
/td
>
{{
/
if
}}
{{
#
each
cell_list
}}
<
td
>
{{
#
if
type
}}
<
div
class
=
"
editable_div
"
data
-
column
=
"
{{column}}
"
data
-
line
=
"
{{line}}
"
><
/div
>
{{
else
}}
{{
#
if
default
}}
{{
default
}}
{{
else
}}
{{
#
if
@
first
}}
Total
{{
/if}
}
{{
/if}
}
{{
/if}
}
<
/td
>
{{
/each}
}
<
/tr
>
{{
/each}
}
<
/tfoot
>
<
/table
>
</script>
<script
id=
"listbox-nav-template"
type=
"text/x-handlebars-template"
>
<
a
class
=
"
{{previous_classname}}
"
data
-
i18n
=
"
Previous
"
href
=
"
{{previous_url}}
"
>
Previous
<
/a
>
<
a
class
=
"
{{next_classname}}
"
data
-
i18n
=
"
Next
"
href
=
"
{{next_url}}
"
>
Next
<
/a
>
<
span
class
=
"
ui-disabled ui-right
"
data
-
i18n
=
"
{{record}}
"
>
{{
record
}}
<
/span
>
</script>
<script
id=
"listbox-template"
type=
"text/x-handlebars-template"
>
<
div
class
=
"
ui-table-header ui-header ui-bar-c ui-corner-all
"
>
<
h1
data
-
i18n
=
"
{{title}}
"
class
=
"
ui-title ui-override-theme
"
>
{{
title
}}
<
span
>
<
span
class
=
"
listboxloader ui-icon-spinner ui-btn-icon-left
"
><
/span></
span
><
/h1
>
...
...
@@ -153,11 +172,11 @@
<
tbody
><
/tbody
>
<
tfoot
class
=
"
ui-bar-inherit tfoot
"
><
/tfoot
>
<
/table
>
<
nav
><
/nav
>
<
/div
>
</script>
<script
id=
"error-message-template"
type=
"text/x-handlebars-template"
>
<
div
class
=
"
ui-listbox-error
"
>
<
a
class
=
"
ui-btn ui-corner-all ui-btn-inline
"
href
=
"
{{reset_url}}
"
>
...
...
bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_listbox_html.xml
View file @
dfb62b97
...
...
@@ -234,7 +234,7 @@
</item>
<item>
<key>
<string>
serial
</string>
</key>
<value>
<string>
96
2.24395.32903.29832
</string>
</value>
<value>
<string>
96
3.63278.21548.22971
</string>
</value>
</item>
<item>
<key>
<string>
state
</string>
</key>
...
...
@@ -252,7 +252,7 @@
</tuple>
<state>
<tuple>
<float>
15
06526285.9
</float>
<float>
15
12617871.97
</float>
<string>
UTC
</string>
</tuple>
</state>
...
...
bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_listbox_js.js
View file @
dfb62b97
...
...
@@ -24,6 +24,11 @@
.
innerHTML
,
listbox_tfoot_template
=
Handlebars
.
compile
(
listbox_tfoot_source
),
listbox_nav_source
=
gadget_klass
.
__template_element
.
getElementById
(
"
listbox-nav-template
"
)
.
innerHTML
,
listbox_nav_template
=
Handlebars
.
compile
(
listbox_nav_source
),
listbox_source
=
gadget_klass
.
__template_element
.
getElementById
(
"
listbox-template
"
)
.
innerHTML
,
...
...
@@ -37,85 +42,96 @@
loading_class_list
=
[
'
ui-icon-spinner
'
,
'
ui-btn-icon-left
'
],
disabled_class
=
'
ui-disabled
'
;
function
renderSubField
(
gadget
,
element
,
sub_field_json
)
{
sub_field_json
.
editable
=
sub_field_json
.
editable
&&
gadget
.
state
.
editable
;
return
gadget
.
declareGadget
(
'
gadget_erp5_label_field.html
'
,
{
element
:
element
,
scope
:
sub_field_json
.
key
}
)
.
push
(
function
(
cell_gadget
)
{
gadget
.
props
.
cell_gadget_list
.
push
(
cell_gadget
);
return
cell_gadget
.
render
({
field_type
:
sub_field_json
.
type
,
field_json
:
sub_field_json
,
label
:
false
});
});
}
function
renderEditableField
(
gadget
,
element
,
column_list
)
{
function
renderEditableField
(
gadget
,
element
,
column_list
,
field_table
)
{
var
i
,
promise_list
=
[],
uid_value_dict
=
{},
uid_value
,
column
,
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
)
{
gadget
.
props
.
cell_gadget_list
.
push
(
cell_gadget
);
return
cell_gadget
.
render
({
field_type
:
sub_field_json
.
type
,
field_json
:
sub_field_json
,
label
:
false
});
});
}
for
(
i
=
0
;
i
<
element_list
.
length
;
i
+=
1
)
{
column
=
element_list
[
i
].
getAttribute
(
"
data-column
"
);
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
;
gadget
.
props
.
listbox_uid_dict
.
value
=
[
gadget
.
state
.
allDocs_result
.
data
.
rows
[
line
].
value
[
"
listbox_uid:list
"
].
value
];
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
],
gadget
.
state
.
allDocs_result
.
data
.
rows
[
line
].
value
[
column_list
[
column
][
0
]]
||
""
));
promise_list
.
push
(
renderSubField
(
gadget
,
element_list
[
i
],
field_table
[
line
].
cell_list
[
column
]
||
""
));
}
return
RSVP
.
all
(
promise_list
);
}
/**Put resulting `row_list` into `template` together with necessary gadget.state parameters.
First, it removes all similar containers from within the table! Currently it is tricky
to have multiple tbody/thead/tfoot elements! Feel free to refactor.
function
renderListboxTbody
(
gadget
,
template
,
body_value
)
{
var
tmp
,
Example call: renderTablePart(gadget, compiled_template, row_list, "tbody");
**/
function
renderTablePart
(
gadget
,
template
,
row_list
,
container_name
)
{
var
container
,
column_list
=
JSON
.
parse
(
gadget
.
state
.
column_list_json
);
return
gadget
.
translateHtml
(
template
(
{
"
body_value
"
:
body_value
,
"
row_list
"
:
row_list
,
"
show_anchor
"
:
gadget
.
state
.
show_anchor
,
"
column_list
"
:
column_list
}
))
.
push
(
function
(
my
_html
)
{
tmp
=
document
.
createElement
(
"
tbody
"
);
tmp
.
innerHTML
=
my
_html
;
return
renderEditableField
(
gadget
,
tmp
,
column
_list
);
.
push
(
function
(
table_part
_html
)
{
container
=
document
.
createElement
(
container_name
);
container
.
innerHTML
=
table_part
_html
;
return
renderEditableField
(
gadget
,
container
,
column_list
,
row
_list
);
})
.
push
(
function
()
{
var
table
=
gadget
.
element
.
querySelector
(
"
table
"
),
tbody
=
table
.
querySelector
(
"
tbody
"
);
table
.
removeChild
(
tbody
);
table
.
appendChild
(
tmp
);
old_container
=
table
.
querySelector
(
container_name
);
if
(
old_container
)
{
table
.
replaceChild
(
container
,
old_container
);
}
else
{
table
.
appendChild
(
container
);
}
return
table
;
});
}
function
renderListboxTfoot
(
gadget
,
foot
)
{
return
gadget
.
translateHtml
(
listbox_tfoot_template
(
{
"
colspan
"
:
foot
.
colspan
,
"
previous_classname
"
:
foot
.
previous_classname
,
"
previous_url
"
:
foot
.
previous_url
,
"
record
"
:
foot
.
record
,
"
next_classname
"
:
foot
.
next_classname
,
"
next_url
"
:
foot
.
next_url
}
));
function
renderListboxTfoot
(
gadget
,
nav
,
foot
)
{
return
renderTablePart
(
gadget
,
listbox_tfoot_template
,
foot
,
"
tfoot
"
)
.
push
(
function
()
{
return
gadget
.
translateHtml
(
listbox_nav_template
(
{
"
previous_classname
"
:
nav
.
previous_classname
,
"
previous_url
"
:
nav
.
previous_url
,
"
record
"
:
nav
.
record
,
"
next_classname
"
:
nav
.
next_classname
,
"
next_url
"
:
nav
.
next_url
}
));
}).
push
(
function
(
listbox_nav_html
)
{
gadget
.
element
.
querySelector
(
'
nav
'
).
innerHTML
=
listbox_nav_html
;
});
}
/** Clojure to ease finding in lists of lists by the first item **/
...
...
@@ -132,7 +148,10 @@
// Init local properties
.
ready
(
function
()
{
this
.
props
=
{
// holds references to all editable sub-fields
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
:
{}
};
})
...
...
@@ -173,7 +192,7 @@
}
/** 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
)
{
if
(
field_json
.
column_list
[
i
][
0
]
===
item
[
0
]
&&
field_json
.
column_list
[
i
][
1
]
===
item
[
1
])
{
return
true
;
...
...
@@ -184,13 +203,14 @@
// use only visible columns for sort
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
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
"
]);
url_query
=
options
.
extended_search
;
query_string
=
new
URI
(
field_json
.
query
).
query
(
true
).
query
;
...
...
@@ -241,6 +261,9 @@
sort_list_json
:
JSON
.
stringify
(
result_list
[
1
]
||
field_json
.
sort
.
map
(
jioize_sort
)),
show_anchor
:
field_json
.
show_anchor
,
show_stat
:
field_json
.
show_stat
,
show_count
:
field_json
.
show_count
,
line_icon
:
field_json
.
line_icon
,
query
:
field_json
.
query
,
query_string
:
query_string
,
...
...
@@ -399,6 +422,8 @@
});
}
/* Function `fetchLineContent` calls changeState({"allDocs_result": JIO.allDocs()})
so this if gets re-evaluated later with allDocs_result defined. */
if
(
gadget
.
state
.
allDocs_result
===
undefined
)
{
// Trigger line content calculation
result_queue
...
...
@@ -414,7 +439,6 @@
}
else
if
((
modification_dict
.
hasOwnProperty
(
'
show_line_selector
'
))
||
(
modification_dict
.
hasOwnProperty
(
'
allDocs_result
'
)))
{
// Render the listbox content
result_queue
.
push
(
function
()
{
...
...
@@ -424,7 +448,7 @@
counter
;
column_list
=
JSON
.
parse
(
gadget
.
state
.
column_list_json
);
// for actual allDocs_result structure see ref:gadget_erp5_jio.js
if
(
lines
===
0
)
{
lines
=
allDocs_result
.
data
.
total_rows
;
counter
=
allDocs_result
.
data
.
total_rows
;
...
...
@@ -432,7 +456,7 @@
counter
=
Math
.
min
(
allDocs_result
.
data
.
total_rows
,
lines
);
}
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
)
{
promise_list
.
push
(
gadget
.
getUrlFor
({
...
...
@@ -453,31 +477,52 @@
return
RSVP
.
all
(
promise_list
);
})
.
push
(
function
(
result_list
)
{
var
value
,
body_value
=
[],
tr_value
=
[],
tmp_url
,
.
push
(
function
(
line_link_list
)
{
var
row_list
=
[],
value
,
cell_list
,
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
)
{
tmp_url
=
result_list
[
i
];
tr_value
=
[];
cell_list
=
[];
for
(
j
=
0
;
j
<
column_list
.
length
;
j
+=
1
)
{
value
=
allDocs_result
.
data
.
rows
[
i
].
value
[
column_list
[
j
][
0
]]
||
""
;
tr_value
.
push
({
"
type
"
:
value
.
type
,
"
editable
"
:
value
.
editable
&&
gadget
.
state
.
editable
,
"
href
"
:
tmp_url
,
"
text
"
:
value
,
"
line
"
:
i
,
"
column
"
:
j
});
// value can be simply just a value in case of non-editable field
// thus we construct "field_json" manually and insert the value in "default"
if
(
value
.
constructor
!==
Object
)
{
value
=
{
'
editable
'
:
0
,
'
default
'
:
value
};
}
value
.
href
=
line_link_list
[
i
];
value
.
editable
=
value
.
editable
&&
gadget
.
state
.
editable
;
value
.
line
=
i
;
value
.
column
=
j
;
cell_list
.
push
(
value
);
}
body_value
.
push
({
"
value
"
:
allDocs_result
.
data
.
rows
[
i
].
value
.
uid
,
"
jump
"
:
tmp_url
,
"
tr_value
"
:
tr_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
({
"
uid
"
:
allDocs_result
.
data
.
rows
[
i
].
value
.
uid
,
"
jump
"
:
line_link_list
[
i
],
"
cell_list
"
:
cell_list
,
"
line_icon
"
:
gadget
.
state
.
line_icon
});
}
...
...
@@ -488,7 +533,7 @@
listbox_tbody_template
=
listbox_hidden_tbody_template
;
}
return
render
ListboxTbody
(
gadget
,
listbox_tbody_template
,
body_value
);
return
render
TablePart
(
gadget
,
listbox_tbody_template
,
row_list
,
"
tbody
"
);
})
.
push
(
function
()
{
var
prev_param
=
{},
...
...
@@ -512,31 +557,50 @@
})
.
push
(
function
(
url_list
)
{
var
foot
=
{};
foot
.
colspan
=
column_list
.
length
+
gadget
.
state
.
show_anchor
+
var
result_sum
=
(
gadget
.
state
.
allDocs_result
.
sum
||
{}).
rows
||
[],
// render summary footer if available
summary
=
result_sum
.
map
(
function
(
row
,
row_index
)
{
var
row_editability
=
row
[
'
listbox_uid:list
'
]
!==
undefined
;
return
{
"
uid
"
:
'
summary
'
+
row_index
,
"
cell_list
"
:
column_list
.
map
(
function
(
col_name
,
col_index
)
{
var
field_json
=
row
.
value
[
col_name
[
0
]]
||
""
;
if
(
field_json
.
constructor
!==
Object
)
{
field_json
=
{
'
default
'
:
field_json
,
'
editable
'
:
0
};
}
field_json
.
editable
=
field_json
.
editable
&&
row_editability
;
field_json
.
column
=
col_index
;
field_json
.
line
=
row_index
;
return
field_json
;
})
};
}),
navigation
=
{
"
previous_url
"
:
url_list
[
0
],
"
next_url
"
:
url_list
[
1
],
"
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
"
};
navigation
.
colspan
=
column_list
.
length
+
gadget
.
state
.
show_anchor
+
(
gadget
.
state
.
line_icon
?
1
:
0
);
foot
.
previous_classname
=
"
ui-btn ui-icon-carat-l ui-btn-icon-left responsive ui-first-child
"
;
foot
.
previous_url
=
url_list
[
0
];
foot
.
next_classname
=
"
ui-btn ui-icon-carat-r ui-btn-icon-right responsive ui-last-child
"
;
foot
.
next_url
=
url_list
[
1
];
if
((
gadget
.
state
.
begin_from
===
0
)
&&
(
counter
===
0
))
{
foot
.
record
=
variable
.
translated_no_record
;
navigation
.
record
=
variable
.
translated_no_record
;
}
else
if
((
allDocs_result
.
data
.
rows
.
length
<=
lines
)
&&
(
gadget
.
state
.
begin_from
===
0
))
{
foot
.
record
=
counter
+
"
"
+
variable
.
translated_records
;
navigation
.
record
=
counter
+
"
"
+
variable
.
translated_records
;
}
else
{
foot
.
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
)
{
foot
.
previous_classname
+=
"
ui-disabled
"
;
navigation
.
previous_classname
+=
"
ui-disabled
"
;
}
if
(
allDocs_result
.
data
.
rows
.
length
<=
lines
)
{
foot
.
next_classname
+=
"
ui-disabled
"
;
navigation
.
next_classname
+=
"
ui-disabled
"
;
}
return
renderListboxTfoot
(
gadget
,
foot
);
return
renderListboxTfoot
(
gadget
,
navigation
,
summary
);
})
.
push
(
function
(
my_html
)
{
gadget
.
element
.
querySelector
(
"
.tfoot
"
).
innerHTML
=
my_html
;
.
push
(
function
()
{
var
loading_element_classList
=
gadget
.
element
.
querySelector
(
"
.listboxloader
"
).
classList
;
loading_element_classList
.
remove
.
apply
(
loading_element_classList
,
loading_class_list
);
});
...
...
@@ -577,7 +641,8 @@
var
gadget
=
this
,
select_list
=
[],
limit_options
,
limit_options
=
[],
aggregation_option_list
=
[],
column_list
=
JSON
.
parse
(
gadget
.
state
.
column_list_json
),
i
;
...
...
@@ -592,6 +657,12 @@
limit_options
=
[
gadget
.
state
.
begin_from
,
gadget
.
state
.
lines
+
1
];
}
if
(
gadget
.
state
.
show_stat
===
true
)
{
aggregation_option_list
.
push
(
"
sum
"
);
}
if
(
gadget
.
state
.
show_count
===
true
)
{
aggregation_option_list
.
push
(
"
count
"
);
}
return
gadget
.
jio_allDocs
({
// XXX Not jIO compatible, but until a better api is found...
...
...
@@ -600,6 +671,7 @@
"
limit
"
:
limit_options
,
"
select_list
"
:
select_list
,
"
sort_on
"
:
JSON
.
parse
(
gadget
.
state
.
sort_list_json
)
// "aggregation": aggregation_option_list
})
.
push
(
function
(
result
)
{
return
gadget
.
changeState
({
...
...
@@ -608,7 +680,7 @@
},
function
(
error
)
{
// 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
)
{
throw
error
;
}
...
...
@@ -620,10 +692,10 @@
})
.
declareMethod
(
"
getContent
"
,
function
(
options
)
{
var
form_
gadget
=
this
,
var
gadget
=
this
,
k
,
field
_gadget
,
count
=
form_
gadget
.
props
.
cell_gadget_list
.
length
,
sub
_gadget
,
count
=
gadget
.
props
.
cell_gadget_list
.
length
,
data
=
{},
queue
=
new
RSVP
.
Queue
();
...
...
@@ -637,17 +709,18 @@
}
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
if
(
field
_gadget
.
getContent
!==
undefined
)
{
if
(
sub
_gadget
.
getContent
!==
undefined
)
{
queue
.
push
(
field_gadget
.
getContent
.
bind
(
field
_gadget
,
options
))
.
push
(
sub_gadget
.
getContent
.
bind
(
sub
_gadget
,
options
))
.
push
(
extendData
);
}
}
return
queue
.
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
;
});
})
...
...
bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_listbox_js.xml
View file @
dfb62b97
...
...
@@ -236,7 +236,7 @@
</item>
<item>
<key>
<string>
serial
</string>
</key>
<value>
<string>
963.
40734.12928.52855
</string>
</value>
<value>
<string>
963.
61737.34616.6621
</string>
</value>
</item>
<item>
<key>
<string>
state
</string>
</key>
...
...
@@ -254,7 +254,7 @@
</tuple>
<state>
<tuple>
<float>
151
1430200.52
</float>
<float>
151
2556744.93
</float>
<string>
UTC
</string>
</tuple>
</state>
...
...
bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_nojqm_css.css
View file @
dfb62b97
...
...
@@ -1279,24 +1279,30 @@ div[data-gadget-scope='erp5_searchfield'] div.search_parsed_value button {
.document_table
table
{
width
:
100%
;
text-align
:
left
;
/* end-of tbody, tfoot*/
}
.document_table
table
th
,
.document_table
table
td
{
vertical-align
:
middle
;
padding
:
3pt
;
}
.document_table
table
thead
{
.document_table
table
thead
,
.document_table
table
tfoot
{
background-color
:
#0E81C2
;
color
:
#FFFFFF
;
}
.document_table
table
thead
a
{
.document_table
table
thead
a
,
.document_table
table
tfoot
a
{
color
:
#FFFFFF
;
text-decoration
:
underline
;
}
.document_table
table
thead
tr
th
{
.document_table
table
thead
tr
th
,
.document_table
table
tfoot
tr
th
{
padding
:
6pt
3pt
;
}
@media
not
screen
and
(
min-width
:
45em
)
{
.document_table
table
thead
{
.document_table
table
thead
,
.document_table
table
tfoot
{
display
:
none
;
}
}
...
...
@@ -1316,7 +1322,6 @@ div[data-gadget-scope='erp5_searchfield'] div.search_parsed_value button {
@media
not
screen
and
(
max-width
:
85em
),
only
screen
and
(
min-width
:
45em
)
and
(
max-width
:
85em
)
{
.document_table
table
tbody
a
{
display
:
block
;
padding
:
3pt
;
}
}
@media
not
screen
and
(
min-width
:
45em
)
{
...
...
@@ -1385,41 +1390,42 @@ div[data-gadget-scope='erp5_searchfield'] div.search_parsed_value button {
content
:
" ~ "
;
}
}
.document_table
table
tfoot
.ui-controlgroup-controls
{
.document_table
nav
{
display
:
flex
;
padding-top
:
6pt
;
border-top
:
2px
solid
rgba
(
0
,
0
,
0
,
0.14902
);
}
.document_table
table
tfoot
.ui-controlgroup-controls
span
{
.document_table
nav
span
{
opacity
:
.3
;
flex
:
2
;
text-align
:
right
;
float
:
right
;
}
.document_table
table
tfoot
.ui-controlgroup-controls
a
{
.document_table
nav
a
{
padding
:
6pt
;
border
:
1px
solid
rgba
(
0
,
0
,
0
,
0.14
);
border-radius
:
0.325em
;
margin-right
:
6pt
;
}
.document_table
table
tfoot
.ui-controlgroup-controls
a
:last-of-type
{
.document_table
nav
a
:last-of-type
{
margin-right
:
0
;
}
.document_table
table
tfoot
.ui-controlgroup-controls
a
:hover
,
.document_table
table
tfoot
.ui-controlgroup-controls
a
:active
{
.document_table
nav
a
:hover
,
.document_table
nav
a
:active
{
background-color
:
#e0e0e0
;
}
@media
not
screen
and
(
min-width
:
45em
)
{
.document_table
table
tfoot
.ui-controlgroup-controls
a
{
.document_table
nav
a
{
overflow
:
hidden
;
text-indent
:
-9999px
;
white-space
:
nowrap
;
}
}
.document_table
table
tfoot
.ui-controlgroup-controls
a
::before
{
.document_table
nav
a
::before
{
margin-right
:
6pt
;
}
@media
not
screen
and
(
min-width
:
45em
)
{
.document_table
table
tfoot
.ui-controlgroup-controls
a
::before
{
.document_table
nav
a
::before
{
float
:
left
;
text-indent
:
6pt
;
}
...
...
bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_nojqm_css.xml
View file @
dfb62b97
...
...
@@ -242,7 +242,7 @@
</item>
<item>
<key>
<string>
serial
</string>
</key>
<value>
<string>
963.
49524.2871.19182
</string>
</value>
<value>
<string>
963.
54869.55137.61115
</string>
</value>
</item>
<item>
<key>
<string>
state
</string>
</key>
...
...
@@ -260,7 +260,7 @@
</tuple>
<state>
<tuple>
<float>
1512
052879.86
</float>
<float>
1512
455490.33
</float>
<string>
UTC
</string>
</tuple>
</state>
...
...
bt5/erp5_web_renderjs_ui/SkinTemplateItem/portal_skins/erp5_web_renderjs_ui/erp5css.less.txt
View file @
dfb62b97
...
...
@@ -1476,9 +1476,10 @@ div[data-gadget-scope='erp5_searchfield'] {
th, td {
// line-height: 1.5em;
vertical-align: middle;
padding: @half-margin-size;
}
thead {
thead
, tfoot
{
background-color: @colorsubheaderbackground;
color: @white;
...
...
@@ -1518,7 +1519,6 @@ div[data-gadget-scope='erp5_searchfield'] {
@media @desktop, @tablet {
a {
display: block;
padding: @half-margin-size;
}
}
...
...
@@ -1598,48 +1598,47 @@ div[data-gadget-scope='erp5_searchfield'] {
}
}
}
} /* end-of tbody, tfoot*/
} /* end-of table */
nav {
display: flex;
padding-top: @margin-size;
border-top: 2px solid rgba(0, 0, 0, 0.14902);
span {
opacity: .3;
flex: 2;
text-align: right;
float: right;
}
a {
padding: @margin-size;
border: 1px solid rgba(0, 0, 0, 0.14);
border-radius: @radius;
margin-right: @margin-size;
&:last-of-type {
margin-right: 0;
}
tfoot .ui-controlgroup-controls {
display: flex;
padding-top: @margin-size;
border-top: 2px solid rgba(0, 0, 0, 0.14902);
&:hover, &:active {
background-color: @colorblocklinkbackground;
}
span {
opacity: .3;
flex: 2;
text-align: right;
@media @smartphone {
.hide_text(@width: initial);
}
a {
padding: @margin-size;
border: 1px solid rgba(0, 0, 0, 0.14);
border-radius: @radius;
&::before {
margin-right: @margin-size;
&:last-of-type {
margin-right: 0;
}
&:hover, &:active {
background-color: @colorblocklinkbackground;
}
@media @smartphone {
.hide_text(@width: initial);
}
&::before {
margin-right: @margin-size;
@media @smartphone {
float: left;
text-indent: @margin-size;
}
float: left;
text-indent: @margin-size;
}
}
}
}
}
...
...
bt5/erp5_web_renderjs_ui_test/PathTemplateItem/portal_tests/renderjs_ui_listbox_zuite/testStatColumns.xml
0 → 100644
View file @
dfb62b97
<?xml version="1.0"?>
<ZopeData>
<record
id=
"1"
aka=
"AAAAAAAAAAE="
>
<pickle>
<global
name=
"ZopePageTemplate"
module=
"Products.PageTemplates.ZopePageTemplate"
/>
</pickle>
<pickle>
<dictionary>
<item>
<key>
<string>
_bind_names
</string>
</key>
<value>
<object>
<klass>
<global
name=
"NameAssignments"
module=
"Shared.DC.Scripts.Bindings"
/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key>
<string>
_asgns
</string>
</key>
<value>
<dictionary>
<item>
<key>
<string>
name_subpath
</string>
</key>
<value>
<string>
traverse_subpath
</string>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key>
<string>
content_type
</string>
</key>
<value>
<string>
text/html
</string>
</value>
</item>
<item>
<key>
<string>
expand
</string>
</key>
<value>
<int>
0
</int>
</value>
</item>
<item>
<key>
<string>
id
</string>
</key>
<value>
<string>
testStatColumns
</string>
</value>
</item>
<item>
<key>
<string>
output_encoding
</string>
</key>
<value>
<string>
utf-8
</string>
</value>
</item>
<item>
<key>
<string>
title
</string>
</key>
<value>
<unicode></unicode>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
bt5/erp5_web_renderjs_ui_test/PathTemplateItem/portal_tests/renderjs_ui_listbox_zuite/testStatColumns.zpt
0 → 100644
View file @
dfb62b97
<html
xmlns:tal=
"http://xml.zope.org/namespaces/tal"
xmlns:metal=
"http://xml.zope.org/namespaces/metal"
>
<!--
Ensure Stat Column methods are executed correctly and result displayed in tfoot element of the listbox table.
- if anchor, then text "Total" is present
- columns which are not present in Stat Columns do not display any data
-->
<head>
<meta
http-equiv=
"Content-Type"
content=
"text/html; charset=UTF-8"
>
<title>
Test RenderJS ListBox Stat Columns
</title>
</head>
<body>
<table
cellpadding=
"1"
cellspacing=
"1"
border=
"1"
>
<thead>
<tr><td
rowspan=
"1"
colspan=
"3"
>
Test RenderJS ListBox Stat Columns
</td></tr>
</thead><tbody>
<tal:block
metal:use-macro=
"here/Zuite_CommonTemplate/macros/init"
/>
<!-- Clean Up -->
<tr><td>
open
</td>
<td>
${base_url}/foo_module/ListBoxZuite_reset
</td><td></td></tr>
<tr><td>
assertTextPresent
</td>
<td>
Reset Successfully.
</td><td></td></tr>
<!-- Shortcut for full renderjs url -->
<tr><td>
store
</td>
<td>
${base_url}/web_site_module/renderjs_runner
</td>
<td>
renderjs_url
</td></tr>
<!-- Create Foo objects with IDs 0-9 -->
<tr><td>
open
</td>
<td>
${base_url}/foo_module/FooModule_createObjects?start:int=1
&
num:int=2
</td><td></td></tr>
<tr><td>
assertTextPresent
</td>
<td>
Created Successfully.
</td><td></td></tr>
<tal:block
metal:use-macro=
"here/Zuite_CommonTemplate/macros/wait_for_activities"
/>
<!-- Let's set up stat column property on listbox -->
<tr><td>
open
</td>
<td>
${base_url}/FooModule_viewFooList/listbox/ListBox_setPropertyList?field_stat_columns=getQuantity+%7C+FooModule_statQuantity+%0A+title+%7C+FooModule_statTitle
</td><td></td></tr>
<tr><td>
assertTextPresent
</td>
<td>
Set Successfully.
</td><td></td></tr>
<tr><td>
open
</td>
<td>
${renderjs_url}/#/foo_module
</td><td></td></tr>
<tr><td>
waitForElementPresent
</td>
<td>
//div[contains(@data-gadget-url, 'gadget_erp5_field_listbox.html')]//nav/span[@data-i18n="2 Records"]
</td><td></td></tr>
<tr><td>
store
</td>
<td>
//div[contains(@data-gadget-url, 'gadget_erp5_field_listbox.html')]//table
</td>
<td>
listbox_table
</td></tr>
<!-- Default sort on ID column has to be ASCENDING -->
<tr><td>
assertFloat
</td>
<td>
${listbox_table}/tbody/tr[1]/td[3]/a
</td>
<td>
9
</td></tr>
<tr><td>
assertFloat
</td>
<td>
${listbox_table}/tbody/tr[2]/td[3]/a
</td>
<td>
8
</td></tr>
<tr><td>
assertText
</td>
<!-- This tests that "Total" appears when first column has no stat defined -->
<td>
${listbox_table}/tfoot/tr[1]/td[1]
</td>
<td>
Total
</td></tr>
<tr><td>
assertText
</td>
<!-- Test multiple Stat Columns -->
<td>
${listbox_table}/tfoot/tr[1]/td[2]
</td>
<td>
Foos
</td></tr>
<tr><td>
assertFloat
</td>
<td>
${listbox_table}/tfoot/tr[1]/td[3]
</td>
<td>
17
</td></tr>
</tbody></table>
</body>
</html>
\ No newline at end of file
bt5/erp5_web_renderjs_ui_test/PathTemplateItem/portal_tests/renderjs_ui_listbox_zuite/testStatMethod.xml
0 → 100644
View file @
dfb62b97
<?xml version="1.0"?>
<ZopeData>
<record
id=
"1"
aka=
"AAAAAAAAAAE="
>
<pickle>
<global
name=
"ZopePageTemplate"
module=
"Products.PageTemplates.ZopePageTemplate"
/>
</pickle>
<pickle>
<dictionary>
<item>
<key>
<string>
_bind_names
</string>
</key>
<value>
<object>
<klass>
<global
name=
"NameAssignments"
module=
"Shared.DC.Scripts.Bindings"
/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key>
<string>
_asgns
</string>
</key>
<value>
<dictionary>
<item>
<key>
<string>
name_subpath
</string>
</key>
<value>
<string>
traverse_subpath
</string>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key>
<string>
content_type
</string>
</key>
<value>
<string>
text/html
</string>
</value>
</item>
<item>
<key>
<string>
expand
</string>
</key>
<value>
<int>
0
</int>
</value>
</item>
<item>
<key>
<string>
id
</string>
</key>
<value>
<string>
testStatMethod
</string>
</value>
</item>
<item>
<key>
<string>
output_encoding
</string>
</key>
<value>
<string>
utf-8
</string>
</value>
</item>
<item>
<key>
<string>
title
</string>
</key>
<value>
<unicode></unicode>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
bt5/erp5_web_renderjs_ui_test/PathTemplateItem/portal_tests/renderjs_ui_listbox_zuite/testStatMethod.zpt
0 → 100644
View file @
dfb62b97
<html
xmlns:tal=
"http://xml.zope.org/namespaces/tal"
xmlns:metal=
"http://xml.zope.org/namespaces/metal"
>
<!--
Ensure stat_method gets executed and result displayed in tfoot element of the listbox table.
- if anchor, then text "Total" is present
- columns for which stat_method does not return any data remain empty
-->
<head>
<meta
http-equiv=
"Content-Type"
content=
"text/html; charset=UTF-8"
>
<title>
Test RenderJS UI ListBox Stat Method
</title>
</head>
<body>
<table
cellpadding=
"1"
cellspacing=
"1"
border=
"1"
>
<thead>
<tr><td
rowspan=
"1"
colspan=
"3"
>
Test RenderJS UI ListBox Stat Method
</td></tr>
</thead><tbody>
<tal:block
metal:use-macro=
"here/Zuite_CommonTemplate/macros/init"
/>
<!-- Clean Up -->
<tr><td>
open
</td>
<td>
${base_url}/foo_module/ListBoxZuite_reset
</td><td></td></tr>
<tr><td>
assertTextPresent
</td>
<td>
Reset Successfully.
</td><td></td></tr>
<!-- Shortcut for full renderjs url -->
<tr><td>
store
</td>
<td>
${base_url}/web_site_module/renderjs_runner
</td>
<td>
renderjs_url
</td></tr>
<!-- Create Foo objects with IDs 0-9 -->
<tr><td>
open
</td>
<td>
${base_url}/foo_module/FooModule_createObjects?start:int=1
&
num:int=3
</td><td></td></tr>
<tr><td>
assertTextPresent
</td>
<td>
Created Successfully.
</td><td></td></tr>
<tal:block
metal:use-macro=
"here/Zuite_CommonTemplate/macros/wait_for_activities"
/>
<!-- Let's set up the default sort correctly: id | ASC -->
<tr><td>
open
</td>
<td>
${base_url}/FooModule_viewFooList/listbox/ListBox_setPropertyList?field_stat_method=FooModule_statMethod
</td><td></td></tr>
<tr><td>
assertTextPresent
</td>
<td>
Set Successfully.
</td><td></td></tr>
<tr><td>
open
</td>
<td>
${renderjs_url}/#/foo_module
</td><td></td></tr>
<tr><td>
waitForElementPresent
</td>
<td>
//div[contains(@data-gadget-url, 'gadget_erp5_field_listbox.html')]//nav/span[@data-i18n="3 Records"]
</td><td></td></tr>
<tr><td>
store
</td>
<td>
//div[contains(@data-gadget-url, 'gadget_erp5_field_listbox.html')]//table
</td>
<td>
listbox_table
</td></tr>
<!-- Default sort on ID column has to be ASCENDING -->
<tr><td>
assertFloat
</td>
<td>
${listbox_table}/tbody/tr[1]/td[3]/a
</td>
<td>
9
</td></tr>
<tr><td>
assertFloat
</td>
<td>
${listbox_table}/tbody/tr[2]/td[3]/a
</td>
<td>
8
</td></tr>
<tr><td>
assertFloat
</td>
<td>
${listbox_table}/tbody/tr[3]/td[3]/a
</td>
<td>
7
</td></tr>
<tr><td>
assertFloat
</td>
<!-- This tests that "Total" does not appear when first column has stat defined -->
<td>
${listbox_table}/tfoot/tr[1]/td[1]
</td>
<td>
6
</td></tr>
<tr><td>
assertFloat
</td>
<td>
${listbox_table}/tfoot/tr[1]/td[3]
</td>
<td>
24
</td></tr>
</tbody></table>
</body>
</html>
\ No newline at end of file
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