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
Labels
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Commits
Open sidebar
Romain Courteaud
erp5
Commits
8fdc1a15
Commit
8fdc1a15
authored
Jan 09, 2018
by
Tomáš Peterka
Committed by
Romain Courteaud
Jan 11, 2018
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[hal_json+renderjs] Implement "stat" line for ListBox
/reviewed-on
nexedi/erp5!528
parent
78bd5926
Changes
23
Hide whitespace changes
Inline
Side-by-side
Showing
23 changed files
with
989 additions
and
202 deletions
+989
-202
bt5/erp5_hal_json_style/SkinTemplateItem/portal_skins/erp5_hal_json_style/ERP5Document_getHateoas.py
...rtal_skins/erp5_hal_json_style/ERP5Document_getHateoas.py
+68
-1
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
+40
-19
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
+167
-95
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
-8
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
+24
-14
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
+28
-25
bt5/erp5_web_renderjs_ui_test/PathTemplateItem/portal_tests/renderjs_ui_listbox_zuite/testEmptyListboxWithStat.xml
...ts/renderjs_ui_listbox_zuite/testEmptyListboxWithStat.xml
+58
-0
bt5/erp5_web_renderjs_ui_test/PathTemplateItem/portal_tests/renderjs_ui_listbox_zuite/testEmptyListboxWithStat.zpt
...ts/renderjs_ui_listbox_zuite/testEmptyListboxWithStat.zpt
+47
-0
bt5/erp5_web_renderjs_ui_test/PathTemplateItem/portal_tests/renderjs_ui_listbox_zuite/testHideItem.zpt
...m/portal_tests/renderjs_ui_listbox_zuite/testHideItem.zpt
+0
-15
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
bt5/erp5_web_renderjs_ui_test/PathTemplateItem/portal_tests/renderjs_ui_listbox_zuite/testStatMissing.xml
...ortal_tests/renderjs_ui_listbox_zuite/testStatMissing.xml
+58
-0
bt5/erp5_web_renderjs_ui_test/PathTemplateItem/portal_tests/renderjs_ui_listbox_zuite/testStatMissing.zpt
...ortal_tests/renderjs_ui_listbox_zuite/testStatMissing.zpt
+53
-0
bt5/erp5_web_renderjs_ui_test/SkinTemplateItem/portal_skins/erp5_web_renderjs_ui_test/Zuite_CommonTemplateForRenderjsUi.zpt
...eb_renderjs_ui_test/Zuite_CommonTemplateForRenderjsUi.zpt
+1
-1
No files found.
bt5/erp5_hal_json_style/SkinTemplateItem/portal_skins/erp5_hal_json_style/ERP5Document_getHateoas.py
View file @
8fdc1a15
...
...
@@ -47,10 +47,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
):
...
...
@@ -684,6 +700,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
(
...
...
@@ -1478,6 +1496,55 @@ def calculateHateoas(is_portal=None, is_site_root=None, traversed_document=None,
contents_list
.
append
(
contents_item
)
result_dict
[
'_embedded'
][
'contents'
]
=
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
# Romain wants full backward compatibility so putting `selection` back in parameters
selection_name
=
source_field
.
get_value
(
'selection_name'
)
if
selection_name
and
'selection_name'
not
in
catalog_kw
:
catalog_kw
[
'selection_name'
]
=
selection_name
catalog_kw
[
'selection'
]
=
context
.
getPortalObject
().
portal_selections
.
getSelectionFor
(
selection_name
,
REQUEST
)
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
)(
REQUEST
=
REQUEST
,
**
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
())(
REQUEST
=
REQUEST
,
**
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'
]
=
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 @
8fdc1a15
"""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 @
8fdc1a15
<?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 @
8fdc1a15
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 @
8fdc1a15
<?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>
selection, **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 @
8fdc1a15
...
...
@@ -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 @
8fdc1a15
...
...
@@ -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 @
8fdc1a15
...
...
@@ -60,18 +60,18 @@
<
/thead
>
<
/table
>
</script>
<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
}}
...
...
@@ -82,7 +82,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
}}
...
...
@@ -101,7 +101,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
>
...
...
@@ -111,7 +111,7 @@
<
td
>
<
input
value
=
"
{{value}}
"
type
=
"
checkbox
"
checked
=
"
true
"
class
=
"
hide_element
"
>
<
/td
>
{{
#
each
tr_value
}}
{{
#
each
cell_list
}}
<
td
>
{{
#
if
type
}}
{{
#
if
editable
}}
...
...
@@ -122,7 +122,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
}}
...
...
@@ -140,19 +140,40 @@
<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
}}
{{
#
unless
..
/
..
/
show_anchor
}}
{{
#
if
@
first
}}
Total
{{
/if}
}
{{
/unless}
}
{{
/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
>
...
...
@@ -165,11 +186,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 @
8fdc1a15
...
...
@@ -234,7 +234,7 @@
</item>
<item>
<key>
<string>
serial
</string>
</key>
<value>
<string>
964.
27340.60822.54681
</string>
</value>
<value>
<string>
964.
45882.29366.36147
</string>
</value>
</item>
<item>
<key>
<string>
state
</string>
</key>
...
...
@@ -252,7 +252,7 @@
</tuple>
<state>
<tuple>
<float>
151
4393372.0
</float>
<float>
151
5514305.55
</float>
<string>
UTC
</string>
</tuple>
</state>
...
...
bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_listbox_js.js
View file @
8fdc1a15
...
...
@@ -28,6 +28,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
,
...
...
@@ -41,88 +46,80 @@
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.
function
renderListboxTbody
(
gadget
,
template
,
body_value
)
{
var
tmp
,
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.
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
}
));
}
/** Clojure to ease finding in lists of lists by the first item **/
function
hasSameFirstItem
(
a
)
{
return
function
(
b
)
{
...
...
@@ -137,7 +134,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
:
{}
};
})
...
...
@@ -272,6 +272,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
,
...
...
@@ -438,6 +441,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
...
...
@@ -453,7 +458,6 @@
}
else
if
((
modification_dict
.
hasOwnProperty
(
'
show_line_selector
'
))
||
(
modification_dict
.
hasOwnProperty
(
'
allDocs_result
'
)))
{
// Render the listbox content
result_queue
.
push
(
function
()
{
...
...
@@ -463,7 +467,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
;
...
...
@@ -471,7 +475,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
({
...
...
@@ -492,31 +496,52 @@
return
RSVP
.
all
(
promise_list
);
})
.
push
(
function
(
result_list
)
{
var
value
,
body_value
=
[],
tr_value
=
[],
tmp_url
,
listbox_tbody_template
;
.
push
(
function
(
line_link_list
)
{
var
row_list
=
[],
value
,
cell_list
,
listbox_tbody_template
,
setNonEditable
=
function
(
cell
)
{
cell
.
editable
=
false
;
};
// 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
);
}
// 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
(
setNonEditable
);
}
body_value
.
push
({
"
value
"
:
allDocs_result
.
data
.
rows
[
i
].
value
.
uid
,
"
jump
"
:
tmp_url
,
"
tr_value
"
:
tr_value
,
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
});
}
...
...
@@ -527,7 +552,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
=
{},
...
...
@@ -551,31 +576,70 @@
})
.
push
(
function
(
url_list
)
{
var
foot
=
{};
foot
.
colspan
=
column_list
.
length
+
gadget
.
state
.
show_anchor
+
(
gadget
.
state
.
line_icon
?
1
:
0
)
+
gadget
.
state
.
show_line_selector
;
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
];
var
record
,
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
"
;
if
((
gadget
.
state
.
begin_from
===
0
)
&&
(
counter
===
0
))
{
foot
.
record
=
variable
.
translated_no_record
;
record
=
variable
.
translated_no_record
;
}
else
if
((
allDocs_result
.
data
.
rows
.
length
<=
lines
)
&&
(
gadget
.
state
.
begin_from
===
0
))
{
foot
.
record
=
counter
+
"
"
+
variable
.
translated_records
;
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
);
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
"
;
previous_classname
+=
"
ui-disabled
"
;
}
if
(
allDocs_result
.
data
.
rows
.
length
<=
lines
)
{
foot
.
next_classname
+=
"
ui-disabled
"
;
next_classname
+=
"
ui-disabled
"
;
}
return
renderListboxTfoot
(
gadget
,
foot
);
return
gadget
.
translateHtml
(
listbox_nav_template
({
"
previous_classname
"
:
previous_classname
,
"
previous_url
"
:
previous_url
,
"
record
"
:
record
,
"
next_classname
"
:
next_classname
,
"
next_url
"
:
next_url
})
)
.
push
(
function
(
listbox_nav_html
)
{
gadget
.
element
.
querySelector
(
'
nav
'
).
innerHTML
=
listbox_nav_html
;
});
})
.
push
(
function
(
my_html
)
{
gadget
.
element
.
querySelector
(
"
.tfoot
"
).
innerHTML
=
my_html
;
.
push
(
function
()
{
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
;
})
};
}),
element
;
if
(
counter
===
0
)
{
// do not render footer (summary) when no data in Listbox because it is ugly
element
=
gadget
.
element
.
querySelector
(
"
table tfoot tr
"
);
if
(
element
!==
null
)
{
element
.
remove
();
}
return
null
;
}
return
renderTablePart
(
gadget
,
listbox_tfoot_template
,
summary
,
"
tfoot
"
);
})
.
push
(
function
()
{
var
loading_element_classList
=
gadget
.
element
.
querySelector
(
"
.listboxloader
"
).
classList
;
loading_element_classList
.
remove
.
apply
(
loading_element_classList
,
loading_class_list
);
});
...
...
@@ -616,7 +680,8 @@
var
gadget
=
this
,
select_list
=
[],
limit_options
,
limit_options
=
[],
aggregation_option_list
=
[],
column_list
=
JSON
.
parse
(
gadget
.
state
.
column_list_json
),
i
;
...
...
@@ -631,6 +696,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...
...
...
@@ -638,6 +709,7 @@
"
query
"
:
gadget
.
state
.
query_string
,
"
limit
"
:
limit_options
,
"
select_list
"
:
select_list
,
// "aggregation": aggregation_option_list
"
sort_on
"
:
JSON
.
parse
(
gadget
.
state
.
sort_list_json
)
})
.
push
(
function
(
result
)
{
...
...
@@ -647,7 +719,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
;
}
...
...
bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_listbox_js.xml
View file @
8fdc1a15
...
...
@@ -75,12 +75,6 @@
<none/>
</value>
</item>
<item>
<key>
<string>
content_type
</string>
</key>
<value>
<none/>
</value>
</item>
<item>
<key>
<string>
default_reference
</string>
</key>
<value>
<string>
gadget_erp5_field_listbox.js
</string>
</value>
...
...
@@ -242,7 +236,7 @@
</item>
<item>
<key>
<string>
serial
</string>
</key>
<value>
<string>
964.
28739.16428.44868
</string>
</value>
<value>
<string>
964.
47502.56518.25890
</string>
</value>
</item>
<item>
<key>
<string>
state
</string>
</key>
...
...
@@ -260,7 +254,7 @@
</tuple>
<state>
<tuple>
<float>
151
4478789.32
</float>
<float>
151
5602869.96
</float>
<string>
UTC
</string>
</tuple>
</state>
...
...
bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_nojqm_css.css
View file @
8fdc1a15
...
...
@@ -1305,24 +1305,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
;
}
}
...
...
@@ -1342,7 +1348,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
)
{
...
...
@@ -1411,41 +1416,46 @@ 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
::before
{
.document_table
nav
a
::before
{
margin-right
:
6pt
;
}
.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
;
}
.document_table
table
tfoot
.ui-controlgroup-controls
a
:last-of-type
{
.document_table
nav
a
:last-of-type
{
margin-right
:
0
;
}
.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
;
}
}
@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/SkinTemplateItem/portal_skins/erp5_web_renderjs_ui/erp5css.less.txt
View file @
8fdc1a15
...
...
@@ -1523,9 +1523,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;
...
...
@@ -1565,7 +1566,6 @@ div[data-gadget-scope='erp5_searchfield'] {
@media @desktop, @tablet {
a {
display: block;
padding: @half-margin-size;
}
}
...
...
@@ -1646,40 +1646,43 @@ div[data-gadget-scope='erp5_searchfield'] {
}
}
}
}
nav {
display: flex;
padding-top: @margin-size;
border-top: 2px solid rgba(0, 0, 0, 0.14902);
tfoot .ui-controlgroup-controls {
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 {
.button();
span {
opacity: .3;
flex: 2;
text-align: right;
margin-right: @margin-size;
&:last-of-type {
margin-right: 0;
}
a {
.button();
margin-right: @margin-size;
&:last-of-type {
margin-right: 0;
}
&:hover, &:active {
background-color: @colorblocklinkbackground;
}
@media @smartphone {
.hide_text(@width: initial);
}
@media @smartphone {
.hide_text(@width: initial);
}
&::before {
&::before {
@media @smartphone {
float: left;
text-indent: @margin-size;
}
@media @smartphone {
float: left;
text-indent: @margin-size;
}
}
}
}
}
...
...
bt5/erp5_web_renderjs_ui_test/PathTemplateItem/portal_tests/renderjs_ui_listbox_zuite/testEmptyListboxWithStat.xml
0 → 100644
View file @
8fdc1a15
<?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>
testEmptyListboxWithStat
</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/testEmptyListboxWithStat.zpt
0 → 100644
View file @
8fdc1a15
<html
xmlns:tal=
"http://xml.zope.org/namespaces/tal"
xmlns:metal=
"http://xml.zope.org/namespaces/metal"
>
<!--
Ensure empty listbox does not show stat line even though it receives stat data.
-->
<head>
<meta
http-equiv=
"Content-Type"
content=
"text/html; charset=UTF-8"
>
<title>
Test RenderJS UI ListBox No Stat Line on No Data
</title>
</head>
<body>
<table
cellpadding=
"1"
cellspacing=
"1"
border=
"1"
>
<thead>
<tr><td
rowspan=
"1"
colspan=
"3"
>
Test RenderJS UI ListBox No Stat Line on No Data
</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>
<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="No records"]
</td><td></td></tr>
<tr><td>
assertElementNotPresent
</td>
<td>
//div[contains(@data-gadget-url, 'gadget_erp5_field_listbox.html')]//table/tfoot/tr
</td>
<td></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/testHideItem.zpt
View file @
8fdc1a15
...
...
@@ -128,11 +128,6 @@
<td>
//thead/tr/th[3]
</td>
<td>
Quantity
</td>
</tr>
<tr>
<td>
assertElementPresent
</td>
<td>
//tfoot/tr/th[@colspan="3"]
</td>
<td></td>
</tr>
<tr>
...
...
@@ -169,11 +164,6 @@
<td>
//thead/tr/th[4]
</td>
<td>
Quantity
</td>
</tr>
<tr>
<td>
assertElementPresent
</td>
<td>
//tfoot/tr/th[@colspan="4"]
</td>
<td></td>
</tr>
<!-- Line checkbox -->
...
...
@@ -233,11 +223,6 @@
<td>
//thead/tr/th[3]
</td>
<td>
Quantity
</td>
</tr>
<tr>
<td>
assertElementPresent
</td>
<td>
//tfoot/tr/th[@colspan="3"]
</td>
<td></td>
</tr>
<!-- only one element present -->
<tr>
...
...
bt5/erp5_web_renderjs_ui_test/PathTemplateItem/portal_tests/renderjs_ui_listbox_zuite/testStatColumns.xml
0 → 100644
View file @
8fdc1a15
<?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 @
8fdc1a15
<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 @
8fdc1a15
<?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 @
8fdc1a15
<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
bt5/erp5_web_renderjs_ui_test/PathTemplateItem/portal_tests/renderjs_ui_listbox_zuite/testStatMissing.xml
0 → 100644
View file @
8fdc1a15
<?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>
testStatMissing
</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/testStatMissing.zpt
0 → 100644
View file @
8fdc1a15
<html
xmlns:tal=
"http://xml.zope.org/namespaces/tal"
xmlns:metal=
"http://xml.zope.org/namespaces/metal"
>
<!--
Ensure no stat line is displayed when no stat_method and no stat_columns are defined.
-->
<head>
<meta
http-equiv=
"Content-Type"
content=
"text/html; charset=UTF-8"
>
<title>
Test RenderJS UI ListBox Stat Missing
</title>
</head>
<body>
<table
cellpadding=
"1"
cellspacing=
"1"
border=
"1"
>
<thead>
<tr><td
rowspan=
"1"
colspan=
"3"
>
Test RenderJS UI ListBox Stat Missing
</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
</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>
assertElementNotPresent
</td>
<td>
//div[contains(@data-gadget-url, 'gadget_erp5_field_listbox.html')]//table/tfoot/tr
</td>
<td></td></tr>
</tbody></table>
</body>
</html>
\ No newline at end of file
bt5/erp5_web_renderjs_ui_test/SkinTemplateItem/portal_skins/erp5_web_renderjs_ui_test/Zuite_CommonTemplateForRenderjsUi.zpt
View file @
8fdc1a15
...
...
@@ -247,7 +247,7 @@
</tr>
<tr>
<td>waitForElementPresent</td>
<td>//div[contains(@data-gadget-url, 'gadget_erp5_field_listbox.html')]//
tfoot
//span[contains(@data-i18n, "Records")]</td>
<td>//div[contains(@data-gadget-url, 'gadget_erp5_field_listbox.html')]//
nav
//span[contains(@data-i18n, "Records")]</td>
<td></td>
</tr>
<tr>
...
...
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