|
1
|
|
|
# -*- coding: utf-8 -*- |
|
2
|
|
|
|
|
3
|
|
|
import json |
|
4
|
|
|
|
|
5
|
|
|
import six |
|
6
|
|
|
|
|
7
|
|
|
from bika.lims import api |
|
8
|
|
|
from AccessControl import ClassSecurityInfo |
|
9
|
|
|
from Products.Archetypes.Registry import registerWidget |
|
10
|
|
|
from Products.Archetypes.Widget import TypesWidget |
|
11
|
|
|
from Products.CMFPlone.utils import base_hasattr |
|
12
|
|
|
|
|
13
|
|
|
_marker = object |
|
14
|
|
|
|
|
15
|
|
|
|
|
16
|
|
|
class QuerySelectWidget(TypesWidget): |
|
17
|
|
|
"""AT Backport of Dexterity Queryselect Widget |
|
18
|
|
|
|
|
19
|
|
|
https://github.com/senaite/senaite.core/pull/2177 |
|
20
|
|
|
""" |
|
21
|
|
|
security = ClassSecurityInfo() |
|
22
|
|
|
_properties = TypesWidget._properties.copy() |
|
23
|
|
|
_properties.update({ |
|
24
|
|
|
"macro": "senaite_widgets/queryselectwidget", |
|
25
|
|
|
"query": {}, |
|
26
|
|
|
"limit": 25, |
|
27
|
|
|
"catalog": "portal_catalog", |
|
28
|
|
|
"api_url": None, |
|
29
|
|
|
"disabled": False, |
|
30
|
|
|
"readonly": False, |
|
31
|
|
|
"multi_valued": False, |
|
32
|
|
|
"allow_user_value": False, |
|
33
|
|
|
"search_wildcard": True, |
|
34
|
|
|
"value_key": "uid", |
|
35
|
|
|
"padding": 3, |
|
36
|
|
|
"display_template": None, |
|
37
|
|
|
"hide_input_after_select": False, |
|
38
|
|
|
}) |
|
39
|
|
|
|
|
40
|
|
View Code Duplication |
def attr(self, context, name, default=None): |
|
|
|
|
|
|
41
|
|
|
"""Get the named attribute of the widget or from the context |
|
42
|
|
|
""" |
|
43
|
|
|
value = getattr(self, name, _marker) |
|
44
|
|
|
if value is _marker: |
|
45
|
|
|
return default |
|
46
|
|
|
if isinstance(value, six.string_types): |
|
47
|
|
|
if base_hasattr(context, value): |
|
48
|
|
|
attr = getattr(context, value) |
|
49
|
|
|
if callable(attr): |
|
50
|
|
|
attr = attr() |
|
51
|
|
|
if attr: |
|
52
|
|
|
value = attr |
|
53
|
|
|
return value |
|
54
|
|
|
|
|
55
|
|
|
def to_value(self, value): |
|
56
|
|
|
"""Extract the value from the request or get it from the field |
|
57
|
|
|
""" |
|
58
|
|
|
# the value might come from the request, e.g. on object creation |
|
59
|
|
|
if isinstance(value, six.string_types): |
|
60
|
|
|
value = filter(None, value.split("\r\n")) |
|
61
|
|
|
# we handle always lists in the templates |
|
62
|
|
|
if value is None: |
|
63
|
|
|
return [] |
|
64
|
|
|
if not isinstance(value, (list, tuple)): |
|
65
|
|
|
value = [value] |
|
66
|
|
|
return value |
|
67
|
|
|
|
|
68
|
|
|
def get_api_url(self, context): |
|
69
|
|
|
"""JSON API URL to use for this widget |
|
70
|
|
|
""" |
|
71
|
|
|
portal = api.get_portal() |
|
72
|
|
|
portal_url = api.get_url(portal) |
|
73
|
|
|
api_url = self.attr(context, "api_url") |
|
74
|
|
|
if not api_url: |
|
75
|
|
|
api_url = "{}/@@API/senaite/v1".format(portal_url) |
|
76
|
|
|
return api_url |
|
77
|
|
|
|
|
78
|
|
|
def get_input_widget_attributes(self, context, field, value): |
|
79
|
|
|
"""Return input widget attributes for the ReactJS component |
|
80
|
|
|
""" |
|
81
|
|
|
attributes = { |
|
82
|
|
|
"data-id": field.getName(), |
|
83
|
|
|
"data-name": field.getName(), |
|
84
|
|
|
"data-values": self.to_value(value), |
|
85
|
|
|
"data-value_key": self.attr(context, "value_key"), |
|
86
|
|
|
"data-columns": self.attr(context, "columns"), |
|
87
|
|
|
"data-query": self.attr(context, "query"), |
|
88
|
|
|
"data-multi_valued": self.attr(context, "multi_valued"), |
|
89
|
|
|
"data-api_url": self.get_api_url(context), |
|
90
|
|
|
"data-search_index": self.attr(context, "search_index"), |
|
91
|
|
|
"data-search_wildcard": self.attr(context, "search_wildcard"), |
|
92
|
|
|
"data-limit": self.attr(context, "limit"), |
|
93
|
|
|
"data-catalog": self.attr(context, "catalog"), |
|
94
|
|
|
"data-allow_user_value": self.attr(context, "allow_user_value"), |
|
95
|
|
|
"data-hide_input_after_select": self.attr( |
|
96
|
|
|
context, "hide_input_after_select"), |
|
97
|
|
|
} |
|
98
|
|
|
|
|
99
|
|
|
# convert all attributes to JSON |
|
100
|
|
|
for key, value in attributes.items(): |
|
101
|
|
|
attributes[key] = json.dumps(value) |
|
102
|
|
|
|
|
103
|
|
|
return attributes |
|
104
|
|
|
|
|
105
|
|
|
|
|
106
|
|
|
registerWidget(QuerySelectWidget, title="QuerySelectWidget") |
|
107
|
|
|
|