author | sylvain.thenault@logilab.fr |
Wed, 11 Mar 2009 19:53:23 +0100 | |
branch | tls-sprint |
changeset 1071 | abe11abb37a0 |
parent 1070 | 3bc7d4ebb543 |
child 1072 | e36f2889e1bd |
permissions | -rw-r--r-- |
0 | 1 |
"""abstract form classes for CubicWeb web client |
2 |
||
3 |
:organization: Logilab |
|
751 | 4 |
:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved. |
0 | 5 |
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr |
6 |
""" |
|
7 |
__docformat__ = "restructuredtext en" |
|
8 |
||
848
f5aca5c5f6ca
set __errorurl, fix retreiving of field's value
sylvain.thenault@logilab.fr
parents:
847
diff
changeset
|
9 |
from warnings import warn |
1016
26387b836099
use datetime instead of mx.DateTime
sylvain.thenault@logilab.fr
parents:
1013
diff
changeset
|
10 |
from datetime import date, datetime |
26387b836099
use datetime instead of mx.DateTime
sylvain.thenault@logilab.fr
parents:
1013
diff
changeset
|
11 |
|
0 | 12 |
from simplejson import dumps |
13 |
||
844 | 14 |
from logilab.common.compat import any |
1058
c27be37daef8
field_by_name method (on class or instance)
sylvain.thenault@logilab.fr
parents:
1056
diff
changeset
|
15 |
from logilab.common.decorators import iclassmethod |
0 | 16 |
from logilab.mtconverter import html_escape |
17 |
||
897
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
18 |
from yams.constraints import SizeConstraint, StaticVocabularyConstraint |
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
19 |
|
0 | 20 |
from cubicweb import typed_eid |
1047
21d4d5e6aa45
make forms selectable (appobject)
sylvain.thenault@logilab.fr
parents:
1032
diff
changeset
|
21 |
from cubicweb.appobject import AppObject |
867
14a79faa3a56
fix implementation errors import DateTimePicker
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
865
diff
changeset
|
22 |
from cubicweb.utils import ustrftime |
1047
21d4d5e6aa45
make forms selectable (appobject)
sylvain.thenault@logilab.fr
parents:
1032
diff
changeset
|
23 |
from cubicweb.selectors import yes, match_form_params, non_final_entity |
751 | 24 |
from cubicweb.view import NOINDEX, NOFOLLOW, View, EntityView, AnyRsetView |
1048 | 25 |
from cubicweb.schema import FormatConstraint |
0 | 26 |
from cubicweb.common.registerers import accepts_registerer |
907 | 27 |
from cubicweb.common.uilib import toggle_action |
0 | 28 |
from cubicweb.web import stdmsgs |
29 |
from cubicweb.web.httpcache import NoHTTPCacheManager |
|
869
168ad6d424d1
form to edit multiple entities, use it in DeleteConfForm
sylvain.thenault@logilab.fr
parents:
867
diff
changeset
|
30 |
from cubicweb.web.controller import NAV_FORM_PARAMETERS, redirect_params |
863
4fde01fc39ca
restore previous hidden input behaviour (edits- / edito- fields)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
849
diff
changeset
|
31 |
from cubicweb.web import INTERNAL_FIELD_VALUE, eid_param |
4fde01fc39ca
restore previous hidden input behaviour (edits- / edito- fields)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
849
diff
changeset
|
32 |
|
0 | 33 |
|
34 |
def relation_id(eid, rtype, target, reid): |
|
35 |
if target == 'subject': |
|
36 |
return u'%s:%s:%s' % (eid, rtype, reid) |
|
37 |
return u'%s:%s:%s' % (reid, rtype, eid) |
|
844 | 38 |
|
39 |
def toggable_relation_link(eid, nodeid, label='x'): |
|
40 |
js = u"javascript: togglePendingDelete('%s', %s);" % (nodeid, html_escape(dumps(eid))) |
|
41 |
return u'[<a class="handle" href="%s" id="handle%s">%s</a>]' % (js, nodeid, label) |
|
0 | 42 |
|
43 |
||
44 |
class FormMixIn(object): |
|
944
e9da555f19c5
[forms] a note (understanding the cause would be nice)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
913
diff
changeset
|
45 |
"""abstract form mix-in |
e9da555f19c5
[forms] a note (understanding the cause would be nice)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
913
diff
changeset
|
46 |
XXX: you should inherit from this FIRST (obscure pb with super call)""" |
0 | 47 |
category = 'form' |
48 |
controller = 'edit' |
|
49 |
domid = 'entityForm' |
|
50 |
||
51 |
http_cache_manager = NoHTTPCacheManager |
|
52 |
add_to_breadcrumbs = False |
|
53 |
skip_relations = set() |
|
54 |
||
55 |
def __init__(self, req, rset): |
|
56 |
super(FormMixIn, self).__init__(req, rset) |
|
57 |
self.maxrelitems = self.req.property_value('navigation.related-limit') |
|
58 |
self.maxcomboitems = self.req.property_value('navigation.combobox-limit') |
|
59 |
self.force_display = not not req.form.get('__force_display') |
|
60 |
# get validation session data which may have been previously set. |
|
61 |
# deleting validation errors here breaks form reloading (errors are |
|
62 |
# no more available), they have to be deleted by application's publish |
|
63 |
# method on successful commit |
|
64 |
formurl = req.url() |
|
65 |
forminfo = req.get_session_data(formurl) |
|
66 |
if forminfo: |
|
67 |
req.data['formvalues'] = forminfo['values'] |
|
68 |
req.data['formerrors'] = errex = forminfo['errors'] |
|
69 |
req.data['displayederrors'] = set() |
|
70 |
# if some validation error occured on entity creation, we have to |
|
71 |
# get the original variable name from its attributed eid |
|
72 |
foreid = errex.entity |
|
73 |
for var, eid in forminfo['eidmap'].items(): |
|
74 |
if foreid == eid: |
|
75 |
errex.eid = var |
|
76 |
break |
|
77 |
else: |
|
78 |
errex.eid = foreid |
|
79 |
||
80 |
def html_headers(self): |
|
81 |
"""return a list of html headers (eg something to be inserted between |
|
82 |
<head> and </head> of the returned page |
|
83 |
||
84 |
by default forms are neither indexed nor followed |
|
85 |
""" |
|
86 |
return [NOINDEX, NOFOLLOW] |
|
87 |
||
88 |
def linkable(self): |
|
89 |
"""override since forms are usually linked by an action, |
|
90 |
so we don't want them to be listed by appli.possible_views |
|
91 |
""" |
|
92 |
return False |
|
93 |
||
94 |
@property |
|
95 |
def limit(self): |
|
96 |
if self.force_display: |
|
97 |
return None |
|
98 |
return self.maxrelitems + 1 |
|
99 |
||
100 |
def need_multipart(self, entity, categories=('primary', 'secondary')): |
|
101 |
"""return a boolean indicating if form's enctype should be multipart |
|
102 |
""" |
|
103 |
for rschema, _, x in entity.relations_by_category(categories): |
|
104 |
if entity.get_widget(rschema, x).need_multipart: |
|
105 |
return True |
|
106 |
# let's find if any of our inlined entities needs multipart |
|
107 |
for rschema, targettypes, x in entity.relations_by_category('inlineview'): |
|
108 |
assert len(targettypes) == 1, \ |
|
109 |
"I'm not able to deal with several targets and inlineview" |
|
110 |
ttype = targettypes[0] |
|
111 |
inlined_entity = self.vreg.etype_class(ttype)(self.req, None, None) |
|
112 |
for irschema, _, x in inlined_entity.relations_by_category(categories): |
|
113 |
if inlined_entity.get_widget(irschema, x).need_multipart: |
|
114 |
return True |
|
115 |
return False |
|
116 |
||
117 |
def error_message(self): |
|
118 |
"""return formatted error message |
|
119 |
||
120 |
This method should be called once inlined field errors has been consumed |
|
121 |
""" |
|
122 |
errex = self.req.data.get('formerrors') |
|
123 |
# get extra errors |
|
124 |
if errex is not None: |
|
125 |
errormsg = self.req._('please correct the following errors:') |
|
126 |
displayed = self.req.data['displayederrors'] |
|
127 |
errors = sorted((field, err) for field, err in errex.errors.items() |
|
128 |
if not field in displayed) |
|
129 |
if errors: |
|
130 |
if len(errors) > 1: |
|
131 |
templstr = '<li>%s</li>\n' |
|
132 |
else: |
|
133 |
templstr = ' %s\n' |
|
134 |
for field, err in errors: |
|
135 |
if field is None: |
|
136 |
errormsg += templstr % err |
|
137 |
else: |
|
138 |
errormsg += templstr % '%s: %s' % (self.req._(field), err) |
|
139 |
if len(errors) > 1: |
|
140 |
errormsg = '<ul>%s</ul>' % errormsg |
|
141 |
return u'<div class="errorMessage">%s</div>' % errormsg |
|
142 |
return u'' |
|
143 |
||
144 |
def restore_pending_inserts(self, entity, cell=False): |
|
145 |
"""used to restore edition page as it was before clicking on |
|
146 |
'search for <some entity type>' |
|
147 |
|
|
148 |
""" |
|
149 |
eid = entity.eid |
|
150 |
cell = cell and "div_insert_" or "tr" |
|
151 |
pending_inserts = set(self.req.get_pending_inserts(eid)) |
|
152 |
for pendingid in pending_inserts: |
|
153 |
eidfrom, rtype, eidto = pendingid.split(':') |
|
154 |
if typed_eid(eidfrom) == entity.eid: # subject |
|
155 |
label = display_name(self.req, rtype, 'subject') |
|
156 |
reid = eidto |
|
157 |
else: |
|
158 |
label = display_name(self.req, rtype, 'object') |
|
159 |
reid = eidfrom |
|
160 |
jscall = "javascript: cancelPendingInsert('%s', '%s', null, %s);" \ |
|
161 |
% (pendingid, cell, eid) |
|
162 |
rset = self.req.eid_rset(reid) |
|
163 |
eview = self.view('text', rset, row=0) |
|
164 |
# XXX find a clean way to handle baskets |
|
165 |
if rset.description[0][0] == 'Basket': |
|
166 |
eview = '%s (%s)' % (eview, display_name(self.req, 'Basket')) |
|
167 |
yield rtype, pendingid, jscall, label, reid, eview |
|
168 |
||
169 |
||
170 |
def force_display_link(self): |
|
171 |
return (u'<span class="invisible">' |
|
172 |
u'[<a href="javascript: window.location.href+=\'&__force_display=1\'">%s</a>]' |
|
173 |
u'</span>' % self.req._('view all')) |
|
174 |
||
175 |
def relations_table(self, entity): |
|
176 |
"""yiels 3-tuples (rtype, target, related_list) |
|
177 |
where <related_list> itself a list of : |
|
178 |
- node_id (will be the entity element's DOM id) |
|
179 |
- appropriate javascript's togglePendingDelete() function call |
|
180 |
- status 'pendingdelete' or '' |
|
181 |
- oneline view of related entity |
|
182 |
""" |
|
183 |
eid = entity.eid |
|
184 |
pending_deletes = self.req.get_pending_deletes(eid) |
|
185 |
# XXX (adim) : quick fix to get Folder relations |
|
186 |
for label, rschema, target in entity.srelations_by_category(('generic', 'metadata'), 'add'): |
|
187 |
if rschema in self.skip_relations: |
|
188 |
continue |
|
189 |
relatedrset = entity.related(rschema, target, limit=self.limit) |
|
190 |
toggable_rel_link = self.toggable_relation_link_func(rschema) |
|
191 |
related = [] |
|
192 |
for row in xrange(relatedrset.rowcount): |
|
193 |
nodeid = relation_id(eid, rschema, target, relatedrset[row][0]) |
|
194 |
if nodeid in pending_deletes: |
|
195 |
status = u'pendingDelete' |
|
196 |
label = '+' |
|
197 |
else: |
|
198 |
status = u'' |
|
199 |
label = 'x' |
|
200 |
dellink = toggable_rel_link(eid, nodeid, label) |
|
201 |
eview = self.view('oneline', relatedrset, row=row) |
|
202 |
related.append((nodeid, dellink, status, eview)) |
|
203 |
yield (rschema, target, related) |
|
204 |
||
205 |
def toggable_relation_link_func(self, rschema): |
|
206 |
if not rschema.has_perm(self.req, 'delete'): |
|
207 |
return lambda x, y, z: u'' |
|
208 |
return toggable_relation_link |
|
209 |
||
210 |
||
211 |
def redirect_url(self, entity=None): |
|
212 |
"""return a url to use as next direction if there are some information |
|
213 |
specified in current form params, else return the result the reset_url |
|
214 |
method which should be defined in concrete classes |
|
215 |
""" |
|
216 |
rparams = redirect_params(self.req.form) |
|
217 |
if rparams: |
|
218 |
return self.build_url('view', **rparams) |
|
219 |
return self.reset_url(entity) |
|
220 |
||
221 |
def reset_url(self, entity): |
|
222 |
raise NotImplementedError('implement me in concrete classes') |
|
223 |
||
224 |
BUTTON_STR = u'<input class="validateButton" type="submit" name="%s" value="%s" tabindex="%s"/>' |
|
225 |
ACTION_SUBMIT_STR = u'<input class="validateButton" type="button" onclick="postForm(\'%s\', \'%s\', \'%s\')" value="%s" tabindex="%s"/>' |
|
226 |
||
227 |
def button_ok(self, label=None, tabindex=None): |
|
228 |
label = self.req._(label or stdmsgs.BUTTON_OK).capitalize() |
|
229 |
return self.BUTTON_STR % ('defaultsubmit', label, tabindex or 2) |
|
230 |
||
231 |
def button_apply(self, label=None, tabindex=None): |
|
232 |
label = self.req._(label or stdmsgs.BUTTON_APPLY).capitalize() |
|
863
4fde01fc39ca
restore previous hidden input behaviour (edits- / edito- fields)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
849
diff
changeset
|
233 |
return self.ACTION_SUBMIT_STR % ('__action_apply', label, self.domid, |
4fde01fc39ca
restore previous hidden input behaviour (edits- / edito- fields)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
849
diff
changeset
|
234 |
label, tabindex or 3) |
0 | 235 |
|
236 |
def button_delete(self, label=None, tabindex=None): |
|
237 |
label = self.req._(label or stdmsgs.BUTTON_DELETE).capitalize() |
|
863
4fde01fc39ca
restore previous hidden input behaviour (edits- / edito- fields)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
849
diff
changeset
|
238 |
return self.ACTION_SUBMIT_STR % ('__action_delete', label, self.domid, |
4fde01fc39ca
restore previous hidden input behaviour (edits- / edito- fields)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
849
diff
changeset
|
239 |
label, tabindex or 3) |
0 | 240 |
|
241 |
def button_cancel(self, label=None, tabindex=None): |
|
242 |
label = self.req._(label or stdmsgs.BUTTON_CANCEL).capitalize() |
|
863
4fde01fc39ca
restore previous hidden input behaviour (edits- / edito- fields)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
849
diff
changeset
|
243 |
return self.ACTION_SUBMIT_STR % ('__action_cancel', label, self.domid, |
4fde01fc39ca
restore previous hidden input behaviour (edits- / edito- fields)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
849
diff
changeset
|
244 |
label, tabindex or 4) |
0 | 245 |
|
246 |
def button_reset(self, label=None, tabindex=None): |
|
247 |
label = self.req._(label or stdmsgs.BUTTON_CANCEL).capitalize() |
|
248 |
return u'<input class="validateButton" type="reset" value="%s" tabindex="%s"/>' % ( |
|
249 |
label, tabindex or 4) |
|
844 | 250 |
|
251 |
||
252 |
############################################################################### |
|
253 |
||
254 |
from cubicweb.common import tags |
|
255 |
||
256 |
# widgets ############ |
|
257 |
||
258 |
class FieldWidget(object): |
|
905
64fd6eaaa9a4
add needs_css and needs_js on widgets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
904
diff
changeset
|
259 |
needs_js = () |
64fd6eaaa9a4
add needs_css and needs_js on widgets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
904
diff
changeset
|
260 |
needs_css = () |
1032
25ec009daa95
by default, don't set id attribute for hidden inputs
sylvain.thenault@logilab.fr
parents:
1031
diff
changeset
|
261 |
setdomid = True |
1055 | 262 |
settabindex = True |
905
64fd6eaaa9a4
add needs_css and needs_js on widgets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
904
diff
changeset
|
263 |
|
1055 | 264 |
def __init__(self, attrs=None, setdomid=None, settabindex=None): |
844 | 265 |
self.attrs = attrs or {} |
1032
25ec009daa95
by default, don't set id attribute for hidden inputs
sylvain.thenault@logilab.fr
parents:
1031
diff
changeset
|
266 |
if setdomid is not None: |
25ec009daa95
by default, don't set id attribute for hidden inputs
sylvain.thenault@logilab.fr
parents:
1031
diff
changeset
|
267 |
# override class's default value |
25ec009daa95
by default, don't set id attribute for hidden inputs
sylvain.thenault@logilab.fr
parents:
1031
diff
changeset
|
268 |
self.setdomid = setdomid |
1055 | 269 |
if settabindex is not None: |
270 |
# override class's default value |
|
271 |
self.settabindex = settabindex |
|
897
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
272 |
|
905
64fd6eaaa9a4
add needs_css and needs_js on widgets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
904
diff
changeset
|
273 |
def add_media(self, form): |
64fd6eaaa9a4
add needs_css and needs_js on widgets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
904
diff
changeset
|
274 |
"""adds media (CSS & JS) required by this widget""" |
64fd6eaaa9a4
add needs_css and needs_js on widgets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
904
diff
changeset
|
275 |
req = form.req |
64fd6eaaa9a4
add needs_css and needs_js on widgets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
904
diff
changeset
|
276 |
if self.needs_js: |
64fd6eaaa9a4
add needs_css and needs_js on widgets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
904
diff
changeset
|
277 |
req.add_js(self.needs_js) |
64fd6eaaa9a4
add needs_css and needs_js on widgets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
904
diff
changeset
|
278 |
if self.needs_css: |
64fd6eaaa9a4
add needs_css and needs_js on widgets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
904
diff
changeset
|
279 |
req.add_css(self.needs_css) |
64fd6eaaa9a4
add needs_css and needs_js on widgets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
904
diff
changeset
|
280 |
|
844 | 281 |
def render(self, form, field): |
282 |
raise NotImplementedError |
|
903
63a8ab7eeb9c
The value as returned by FieldWidget._render_attrs() is now always a list
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
902
diff
changeset
|
283 |
|
63a8ab7eeb9c
The value as returned by FieldWidget._render_attrs() is now always a list
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
902
diff
changeset
|
284 |
def _render_attrs(self, form, field): |
63a8ab7eeb9c
The value as returned by FieldWidget._render_attrs() is now always a list
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
902
diff
changeset
|
285 |
name = form.context[field]['name'] |
63a8ab7eeb9c
The value as returned by FieldWidget._render_attrs() is now always a list
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
902
diff
changeset
|
286 |
values = form.context[field]['value'] |
63a8ab7eeb9c
The value as returned by FieldWidget._render_attrs() is now always a list
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
902
diff
changeset
|
287 |
if not isinstance(values, (tuple, list)): |
63a8ab7eeb9c
The value as returned by FieldWidget._render_attrs() is now always a list
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
902
diff
changeset
|
288 |
values = (values,) |
907 | 289 |
attrs = dict(self.attrs) |
1032
25ec009daa95
by default, don't set id attribute for hidden inputs
sylvain.thenault@logilab.fr
parents:
1031
diff
changeset
|
290 |
if self.setdomid: |
25ec009daa95
by default, don't set id attribute for hidden inputs
sylvain.thenault@logilab.fr
parents:
1031
diff
changeset
|
291 |
attrs['id'] = form.context[field]['id'] |
1055 | 292 |
if self.settabindex: |
293 |
attrs['tabindex'] = form.req.next_tabindex() |
|
910
a86ab461b8fd
fix DateTimePicker implementation, it should now work
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
907
diff
changeset
|
294 |
return name, values, attrs |
903
63a8ab7eeb9c
The value as returned by FieldWidget._render_attrs() is now always a list
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
902
diff
changeset
|
295 |
|
844 | 296 |
class Input(FieldWidget): |
297 |
type = None |
|
298 |
||
299 |
def render(self, form, field): |
|
905
64fd6eaaa9a4
add needs_css and needs_js on widgets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
904
diff
changeset
|
300 |
self.add_media(form) |
903
63a8ab7eeb9c
The value as returned by FieldWidget._render_attrs() is now always a list
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
902
diff
changeset
|
301 |
name, values, attrs = self._render_attrs(form, field) |
63a8ab7eeb9c
The value as returned by FieldWidget._render_attrs() is now always a list
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
902
diff
changeset
|
302 |
inputs = [tags.input(name=name, value=value, type=self.type, **attrs) |
63a8ab7eeb9c
The value as returned by FieldWidget._render_attrs() is now always a list
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
902
diff
changeset
|
303 |
for value in values] |
63a8ab7eeb9c
The value as returned by FieldWidget._render_attrs() is now always a list
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
902
diff
changeset
|
304 |
return u'\n'.join(inputs) |
844 | 305 |
|
306 |
class TextInput(Input): |
|
307 |
type = 'text' |
|
308 |
||
309 |
class PasswordInput(Input): |
|
310 |
type = 'password' |
|
908
136d91725ecf
confirmation in password widget
sylvain.thenault@logilab.fr
parents:
907
diff
changeset
|
311 |
|
136d91725ecf
confirmation in password widget
sylvain.thenault@logilab.fr
parents:
907
diff
changeset
|
312 |
def render(self, form, field): |
136d91725ecf
confirmation in password widget
sylvain.thenault@logilab.fr
parents:
907
diff
changeset
|
313 |
self.add_media(form) |
136d91725ecf
confirmation in password widget
sylvain.thenault@logilab.fr
parents:
907
diff
changeset
|
314 |
name, values, attrs = self._render_attrs(form, field) |
911 | 315 |
assert len(values) == 1 |
316 |
inputs = [tags.input(name=name, value=values[0], type=self.type, **attrs), |
|
908
136d91725ecf
confirmation in password widget
sylvain.thenault@logilab.fr
parents:
907
diff
changeset
|
317 |
'<br/>', |
136d91725ecf
confirmation in password widget
sylvain.thenault@logilab.fr
parents:
907
diff
changeset
|
318 |
tags.input(name=name+'-confirm', type=self.type, **attrs), |
136d91725ecf
confirmation in password widget
sylvain.thenault@logilab.fr
parents:
907
diff
changeset
|
319 |
' ', tags.span(form.req._('confirm password'), |
136d91725ecf
confirmation in password widget
sylvain.thenault@logilab.fr
parents:
907
diff
changeset
|
320 |
**{'class': 'emphasis'})] |
136d91725ecf
confirmation in password widget
sylvain.thenault@logilab.fr
parents:
907
diff
changeset
|
321 |
return u'\n'.join(inputs) |
844 | 322 |
|
323 |
class FileInput(Input): |
|
324 |
type = 'file' |
|
907 | 325 |
|
326 |
def _render_attrs(self, form, field): |
|
327 |
# ignore value which makes no sense here (XXX even on form validation error?) |
|
328 |
name, values, attrs = super(FileInput, self)._render_attrs(form, field) |
|
329 |
return name, ('',), attrs |
|
330 |
||
844 | 331 |
class HiddenInput(Input): |
332 |
type = 'hidden' |
|
1032
25ec009daa95
by default, don't set id attribute for hidden inputs
sylvain.thenault@logilab.fr
parents:
1031
diff
changeset
|
333 |
setdomid = False # by default, don't set id attribute on hidden input |
1055 | 334 |
settabindex = False |
897
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
335 |
|
907 | 336 |
class ButtonInput(Input): |
844 | 337 |
type = 'button' |
338 |
||
339 |
class TextArea(FieldWidget): |
|
340 |
def render(self, form, field): |
|
903
63a8ab7eeb9c
The value as returned by FieldWidget._render_attrs() is now always a list
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
902
diff
changeset
|
341 |
name, values, attrs = self._render_attrs(form, field) |
892
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
342 |
attrs.setdefault('onkeypress', 'autogrow(this)') |
903
63a8ab7eeb9c
The value as returned by FieldWidget._render_attrs() is now always a list
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
902
diff
changeset
|
343 |
if not values: |
63a8ab7eeb9c
The value as returned by FieldWidget._render_attrs() is now always a list
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
902
diff
changeset
|
344 |
value = u'' |
63a8ab7eeb9c
The value as returned by FieldWidget._render_attrs() is now always a list
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
902
diff
changeset
|
345 |
elif len(values) == 1: |
63a8ab7eeb9c
The value as returned by FieldWidget._render_attrs() is now always a list
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
902
diff
changeset
|
346 |
value = values[0] |
63a8ab7eeb9c
The value as returned by FieldWidget._render_attrs() is now always a list
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
902
diff
changeset
|
347 |
else: |
63a8ab7eeb9c
The value as returned by FieldWidget._render_attrs() is now always a list
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
902
diff
changeset
|
348 |
raise ValueError('a textarea is not supposed to be multivalued') |
844 | 349 |
return tags.textarea(value, name=name, **attrs) |
350 |
||
907 | 351 |
|
892
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
352 |
class FCKEditor(TextArea): |
1059 | 353 |
def __init__(self, *args, **kwargs): |
354 |
super(FCKEditor, self).__init__(*args, **kwargs) |
|
892
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
355 |
self.attrs['cubicweb:type'] = 'wysiwyg' |
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
356 |
|
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
357 |
def render(self, form, field): |
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
358 |
form.req.fckeditor_config() |
1059 | 359 |
return super(FCKEditor, self).render(form, field) |
892
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
360 |
|
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
361 |
|
864
e0947007542a
basic implementation of Date / Float fields
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
863
diff
changeset
|
362 |
class Select(FieldWidget): |
903
63a8ab7eeb9c
The value as returned by FieldWidget._render_attrs() is now always a list
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
902
diff
changeset
|
363 |
def __init__(self, attrs=None, multiple=False): |
892
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
364 |
super(Select, self).__init__(attrs) |
901
0dcf01eb97a0
implement default vocabulary method on Field, provide a specific one on RelationField
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
900
diff
changeset
|
365 |
self.multiple = multiple |
864
e0947007542a
basic implementation of Date / Float fields
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
863
diff
changeset
|
366 |
|
844 | 367 |
def render(self, form, field): |
903
63a8ab7eeb9c
The value as returned by FieldWidget._render_attrs() is now always a list
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
902
diff
changeset
|
368 |
name, curvalues, attrs = self._render_attrs(form, field) |
844 | 369 |
options = [] |
1056 | 370 |
for label, value in field.vocabulary(form): |
903
63a8ab7eeb9c
The value as returned by FieldWidget._render_attrs() is now always a list
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
902
diff
changeset
|
371 |
if value in curvalues: |
63a8ab7eeb9c
The value as returned by FieldWidget._render_attrs() is now always a list
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
902
diff
changeset
|
372 |
options.append(tags.option(label, value=value, selected='selected')) |
63a8ab7eeb9c
The value as returned by FieldWidget._render_attrs() is now always a list
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
902
diff
changeset
|
373 |
else: |
63a8ab7eeb9c
The value as returned by FieldWidget._render_attrs() is now always a list
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
902
diff
changeset
|
374 |
options.append(tags.option(label, value=value)) |
901
0dcf01eb97a0
implement default vocabulary method on Field, provide a specific one on RelationField
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
900
diff
changeset
|
375 |
return tags.select(name=name, multiple=self.multiple, |
0dcf01eb97a0
implement default vocabulary method on Field, provide a specific one on RelationField
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
900
diff
changeset
|
376 |
options=options, **attrs) |
844 | 377 |
|
378 |
||
907 | 379 |
class CheckBox(Input): |
380 |
type = 'checkbox' |
|
381 |
||
1067
f37ee6855e42
checkbox widget should use vocabulary
sylvain.thenault@logilab.fr
parents:
1064
diff
changeset
|
382 |
def render(self, form, field): |
f37ee6855e42
checkbox widget should use vocabulary
sylvain.thenault@logilab.fr
parents:
1064
diff
changeset
|
383 |
name, curvalues, attrs = self._render_attrs(form, field) |
f37ee6855e42
checkbox widget should use vocabulary
sylvain.thenault@logilab.fr
parents:
1064
diff
changeset
|
384 |
options = [] |
f37ee6855e42
checkbox widget should use vocabulary
sylvain.thenault@logilab.fr
parents:
1064
diff
changeset
|
385 |
for label, value in field.vocabulary(form): |
f37ee6855e42
checkbox widget should use vocabulary
sylvain.thenault@logilab.fr
parents:
1064
diff
changeset
|
386 |
if value in curvalues: |
f37ee6855e42
checkbox widget should use vocabulary
sylvain.thenault@logilab.fr
parents:
1064
diff
changeset
|
387 |
tag = tags.input(name=name, value=value, type=self.type, |
f37ee6855e42
checkbox widget should use vocabulary
sylvain.thenault@logilab.fr
parents:
1064
diff
changeset
|
388 |
checked='checked', **attrs) |
f37ee6855e42
checkbox widget should use vocabulary
sylvain.thenault@logilab.fr
parents:
1064
diff
changeset
|
389 |
else: |
f37ee6855e42
checkbox widget should use vocabulary
sylvain.thenault@logilab.fr
parents:
1064
diff
changeset
|
390 |
tag = tags.input(name=name, value=value, type=self.type, |
f37ee6855e42
checkbox widget should use vocabulary
sylvain.thenault@logilab.fr
parents:
1064
diff
changeset
|
391 |
**attrs) |
f37ee6855e42
checkbox widget should use vocabulary
sylvain.thenault@logilab.fr
parents:
1064
diff
changeset
|
392 |
options.append(tag + label) |
f37ee6855e42
checkbox widget should use vocabulary
sylvain.thenault@logilab.fr
parents:
1064
diff
changeset
|
393 |
return '<br/>\n'.join(options) |
892
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
394 |
|
865
90a1aea85637
DatePicker widget
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
864
diff
changeset
|
395 |
|
1056 | 396 |
class Radio(Input): |
397 |
type = 'radio' |
|
398 |
setdomid = False |
|
399 |
||
400 |
def render(self, form, field): |
|
401 |
name, curvalues, attrs = self._render_attrs(form, field) |
|
402 |
options = [] |
|
403 |
for label, value in field.vocabulary(form): |
|
404 |
if value in curvalues: |
|
405 |
options.append(tags.input(name=name, type=self.type, value=value, checked='checked', **attrs)) |
|
406 |
else: |
|
407 |
options.append(tags.option(name=name, type=self.type, value=value, **attrs)) |
|
408 |
options[-1] += label + '<br/>' |
|
409 |
return '\n'.join(options) |
|
865
90a1aea85637
DatePicker widget
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
864
diff
changeset
|
410 |
|
892
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
411 |
|
865
90a1aea85637
DatePicker widget
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
864
diff
changeset
|
412 |
class DateTimePicker(TextInput): |
907 | 413 |
monthnames = ('january', 'february', 'march', 'april', |
414 |
'may', 'june', 'july', 'august', |
|
415 |
'september', 'october', 'november', 'december') |
|
416 |
daynames = ('monday', 'tuesday', 'wednesday', 'thursday', |
|
417 |
'friday', 'saturday', 'sunday') |
|
865
90a1aea85637
DatePicker widget
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
864
diff
changeset
|
418 |
|
905
64fd6eaaa9a4
add needs_css and needs_js on widgets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
904
diff
changeset
|
419 |
needs_js = ('cubicweb.ajax.js', 'cubicweb.calendar.js') |
64fd6eaaa9a4
add needs_css and needs_js on widgets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
904
diff
changeset
|
420 |
needs_css = ('cubicweb.calendar_popup.css',) |
64fd6eaaa9a4
add needs_css and needs_js on widgets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
904
diff
changeset
|
421 |
|
865
90a1aea85637
DatePicker widget
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
864
diff
changeset
|
422 |
@classmethod |
90a1aea85637
DatePicker widget
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
864
diff
changeset
|
423 |
def add_localized_infos(cls, req): |
90a1aea85637
DatePicker widget
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
864
diff
changeset
|
424 |
"""inserts JS variables defining localized months and days""" |
90a1aea85637
DatePicker widget
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
864
diff
changeset
|
425 |
# import here to avoid dependancy from cubicweb-common to simplejson |
90a1aea85637
DatePicker widget
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
864
diff
changeset
|
426 |
_ = req._ |
90a1aea85637
DatePicker widget
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
864
diff
changeset
|
427 |
monthnames = [_(mname) for mname in cls.monthnames] |
90a1aea85637
DatePicker widget
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
864
diff
changeset
|
428 |
daynames = [_(dname) for dname in cls.daynames] |
90a1aea85637
DatePicker widget
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
864
diff
changeset
|
429 |
req.html_headers.define_var('MONTHNAMES', monthnames) |
90a1aea85637
DatePicker widget
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
864
diff
changeset
|
430 |
req.html_headers.define_var('DAYNAMES', daynames) |
90a1aea85637
DatePicker widget
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
864
diff
changeset
|
431 |
|
90a1aea85637
DatePicker widget
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
864
diff
changeset
|
432 |
def render(self, form, field): |
90a1aea85637
DatePicker widget
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
864
diff
changeset
|
433 |
txtwidget = super(DateTimePicker, self).render(form, field) |
910
a86ab461b8fd
fix DateTimePicker implementation, it should now work
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
907
diff
changeset
|
434 |
self.add_localized_infos(form.req) |
867
14a79faa3a56
fix implementation errors import DateTimePicker
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
865
diff
changeset
|
435 |
cal_button = self._render_calendar_popup(form, field) |
865
90a1aea85637
DatePicker widget
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
864
diff
changeset
|
436 |
return txtwidget + cal_button |
90a1aea85637
DatePicker widget
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
864
diff
changeset
|
437 |
|
90a1aea85637
DatePicker widget
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
864
diff
changeset
|
438 |
def _render_calendar_popup(self, form, field): |
90a1aea85637
DatePicker widget
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
864
diff
changeset
|
439 |
req = form.req |
867
14a79faa3a56
fix implementation errors import DateTimePicker
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
865
diff
changeset
|
440 |
value = form.context[field]['rawvalue'] |
14a79faa3a56
fix implementation errors import DateTimePicker
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
865
diff
changeset
|
441 |
inputid = form.context[field]['id'] |
14a79faa3a56
fix implementation errors import DateTimePicker
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
865
diff
changeset
|
442 |
helperid = '%shelper' % inputid |
865
90a1aea85637
DatePicker widget
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
864
diff
changeset
|
443 |
if not value: |
1016
26387b836099
use datetime instead of mx.DateTime
sylvain.thenault@logilab.fr
parents:
1013
diff
changeset
|
444 |
value = date.today() |
865
90a1aea85637
DatePicker widget
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
864
diff
changeset
|
445 |
year, month = value.year, value.month |
90a1aea85637
DatePicker widget
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
864
diff
changeset
|
446 |
onclick = "toggleCalendar('%s', '%s', %s, %s);" % ( |
867
14a79faa3a56
fix implementation errors import DateTimePicker
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
865
diff
changeset
|
447 |
helperid, inputid, year, month) |
865
90a1aea85637
DatePicker widget
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
864
diff
changeset
|
448 |
return (u"""<a onclick="toggleCalendar('%s', '%s', %s, %s);" class="calhelper"> |
90a1aea85637
DatePicker widget
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
864
diff
changeset
|
449 |
<img src="%s" title="%s" alt="" /></a><div class="calpopup hidden" id="%s"></div>""" |
90a1aea85637
DatePicker widget
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
864
diff
changeset
|
450 |
% (helperid, inputid, year, month, |
867
14a79faa3a56
fix implementation errors import DateTimePicker
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
865
diff
changeset
|
451 |
req.external_resource('CALENDAR_ICON'), |
14a79faa3a56
fix implementation errors import DateTimePicker
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
865
diff
changeset
|
452 |
req._('calendar'), helperid) ) |
844 | 453 |
|
454 |
||
1069 | 455 |
class AjaxWidget(FieldWidget): |
456 |
def __init__(self, wdgtype, inputid=None, **kwargs): |
|
457 |
super(AjaxWidget, self).__init__(**kwargs) |
|
458 |
self.attrs.setdefault('class', 'widget') |
|
459 |
self.attrs.setdefault('cubicweb:loadtype', 'auto') |
|
460 |
self.attrs['cubicweb:wdgtype'] = wdgtype |
|
461 |
if inputid is not None: |
|
462 |
self.attrs['cubicweb:inputid'] = inputid |
|
463 |
||
464 |
def render(self, form, field): |
|
465 |
self.add_media(form) |
|
466 |
name, values, attrs = self._render_attrs(form, field) |
|
467 |
return tags.div(**attrs) |
|
468 |
||
469 |
||
844 | 470 |
# fields ############ |
471 |
||
472 |
class Field(object): |
|
473 |
"""field class is introduced to control what's displayed in edition form |
|
474 |
""" |
|
475 |
widget = TextInput |
|
476 |
needs_multipart = False |
|
477 |
creation_rank = 0 |
|
904
4f1ce95aa686
fix label generation in forms
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
903
diff
changeset
|
478 |
|
844 | 479 |
def __init__(self, name=None, id=None, label=None, |
901
0dcf01eb97a0
implement default vocabulary method on Field, provide a specific one on RelationField
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
900
diff
changeset
|
480 |
widget=None, required=False, initial=None, |
0dcf01eb97a0
implement default vocabulary method on Field, provide a specific one on RelationField
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
900
diff
changeset
|
481 |
choices=None, help=None, eidparam=False): |
844 | 482 |
self.required = required |
483 |
if widget is not None: |
|
484 |
self.widget = widget |
|
485 |
if isinstance(self.widget, type): |
|
486 |
self.widget = self.widget() |
|
487 |
self.name = name |
|
488 |
self.label = label or name |
|
489 |
self.id = id or name |
|
490 |
self.initial = initial |
|
1070
3bc7d4ebb543
if choices is None, call form_field_vocabulary
sylvain.thenault@logilab.fr
parents:
1069
diff
changeset
|
491 |
self.choices = choices |
844 | 492 |
self.help = help |
493 |
self.eidparam = eidparam |
|
901
0dcf01eb97a0
implement default vocabulary method on Field, provide a specific one on RelationField
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
900
diff
changeset
|
494 |
self.role = 'subject' |
844 | 495 |
# global fields ordering in forms |
1071
abe11abb37a0
must record creation rank as an instance attribute
sylvain.thenault@logilab.fr
parents:
1070
diff
changeset
|
496 |
self.creation_rank = Field.creation_rank |
844 | 497 |
Field.creation_rank += 1 |
498 |
||
499 |
def set_name(self, name): |
|
892
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
500 |
assert name |
844 | 501 |
self.name = name |
502 |
if not self.id: |
|
503 |
self.id = name |
|
504 |
if not self.label: |
|
505 |
self.label = name |
|
892
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
506 |
|
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
507 |
def is_visible(self): |
904
4f1ce95aa686
fix label generation in forms
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
903
diff
changeset
|
508 |
return not isinstance(self.widget, HiddenInput) |
892
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
509 |
|
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
510 |
def actual_fields(self, form): |
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
511 |
yield self |
844 | 512 |
|
900
8f95ebbe2fd8
field debug helper
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
899
diff
changeset
|
513 |
def __unicode__(self): |
8f95ebbe2fd8
field debug helper
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
899
diff
changeset
|
514 |
return u'<%s name=%r label=%r id=%r initial=%r>' % ( |
8f95ebbe2fd8
field debug helper
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
899
diff
changeset
|
515 |
self.__class__.__name__, self.name, self.label, |
8f95ebbe2fd8
field debug helper
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
899
diff
changeset
|
516 |
self.id, self.initial) |
8f95ebbe2fd8
field debug helper
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
899
diff
changeset
|
517 |
|
8f95ebbe2fd8
field debug helper
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
899
diff
changeset
|
518 |
def __repr__(self): |
8f95ebbe2fd8
field debug helper
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
899
diff
changeset
|
519 |
return self.__unicode__().encode('utf-8') |
8f95ebbe2fd8
field debug helper
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
899
diff
changeset
|
520 |
|
844 | 521 |
def format_value(self, req, value): |
903
63a8ab7eeb9c
The value as returned by FieldWidget._render_attrs() is now always a list
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
902
diff
changeset
|
522 |
if isinstance(value, (list, tuple)): |
63a8ab7eeb9c
The value as returned by FieldWidget._render_attrs() is now always a list
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
902
diff
changeset
|
523 |
return [self.format_single_value(req, val) for val in value] |
63a8ab7eeb9c
The value as returned by FieldWidget._render_attrs() is now always a list
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
902
diff
changeset
|
524 |
return self.format_single_value(req, value) |
63a8ab7eeb9c
The value as returned by FieldWidget._render_attrs() is now always a list
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
902
diff
changeset
|
525 |
|
63a8ab7eeb9c
The value as returned by FieldWidget._render_attrs() is now always a list
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
902
diff
changeset
|
526 |
def format_single_value(self, req, value): |
63a8ab7eeb9c
The value as returned by FieldWidget._render_attrs() is now always a list
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
902
diff
changeset
|
527 |
if value is None: |
63a8ab7eeb9c
The value as returned by FieldWidget._render_attrs() is now always a list
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
902
diff
changeset
|
528 |
return u'' |
844 | 529 |
return unicode(value) |
530 |
||
907 | 531 |
def get_widget(self, form): |
892
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
532 |
return self.widget |
907 | 533 |
|
534 |
def example_format(self, req): |
|
535 |
return u'' |
|
892
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
536 |
|
907 | 537 |
def render(self, form, renderer): |
538 |
return self.get_widget(form).render(form, self) |
|
892
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
539 |
|
901
0dcf01eb97a0
implement default vocabulary method on Field, provide a specific one on RelationField
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
900
diff
changeset
|
540 |
def vocabulary(self, form): |
1070
3bc7d4ebb543
if choices is None, call form_field_vocabulary
sylvain.thenault@logilab.fr
parents:
1069
diff
changeset
|
541 |
if self.choices is not None: |
3bc7d4ebb543
if choices is None, call form_field_vocabulary
sylvain.thenault@logilab.fr
parents:
1069
diff
changeset
|
542 |
return self.choices |
3bc7d4ebb543
if choices is None, call form_field_vocabulary
sylvain.thenault@logilab.fr
parents:
1069
diff
changeset
|
543 |
return form.form_field_vocabulary(self) |
907 | 544 |
|
901
0dcf01eb97a0
implement default vocabulary method on Field, provide a specific one on RelationField
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
900
diff
changeset
|
545 |
|
844 | 546 |
class StringField(Field): |
547 |
def __init__(self, max_length=None, **kwargs): |
|
548 |
super(StringField, self).__init__(**kwargs) |
|
549 |
self.max_length = max_length |
|
892
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
550 |
|
907 | 551 |
|
844 | 552 |
class TextField(Field): |
907 | 553 |
widget = TextArea |
903
63a8ab7eeb9c
The value as returned by FieldWidget._render_attrs() is now always a list
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
902
diff
changeset
|
554 |
def __init__(self, rows=10, cols=80, **kwargs): |
907 | 555 |
super(TextField, self).__init__(**kwargs) |
903
63a8ab7eeb9c
The value as returned by FieldWidget._render_attrs() is now always a list
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
902
diff
changeset
|
556 |
self.rows = rows |
63a8ab7eeb9c
The value as returned by FieldWidget._render_attrs() is now always a list
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
902
diff
changeset
|
557 |
self.cols = cols |
892
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
558 |
|
907 | 559 |
|
892
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
560 |
class RichTextField(TextField): |
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
561 |
widget = None |
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
562 |
def __init__(self, format_field=None, **kwargs): |
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
563 |
super(RichTextField, self).__init__(**kwargs) |
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
564 |
self.format_field = format_field |
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
565 |
|
907 | 566 |
def get_widget(self, form): |
892
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
567 |
if self.widget is None: |
907 | 568 |
if self.use_fckeditor(form): |
892
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
569 |
return FCKEditor() |
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
570 |
return TextArea() |
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
571 |
return self.widget |
844 | 572 |
|
892
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
573 |
def get_format_field(self, form): |
907 | 574 |
if self.format_field: |
575 |
return self.format_field |
|
576 |
# we have to cache generated field since it's use as key in the |
|
577 |
# context dictionnary |
|
1064 | 578 |
req = form.req |
907 | 579 |
try: |
1064 | 580 |
return req.data[self] |
907 | 581 |
except KeyError: |
892
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
582 |
if self.use_fckeditor(form): |
907 | 583 |
# if fckeditor is used and format field isn't explicitly |
584 |
# deactivated, we want an hidden field for the format |
|
585 |
widget = HiddenInput() |
|
1048 | 586 |
choices = None |
892
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
587 |
else: |
907 | 588 |
# else we want a format selector |
589 |
# XXX compute vocabulary |
|
892
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
590 |
widget = Select |
1048 | 591 |
choices = [(req._(format), format) for format in FormatConstraint().vocabulary(req=req)] |
592 |
field = StringField(name=self.name + '_format', widget=widget, |
|
593 |
choices=choices) |
|
1064 | 594 |
req.data[self] = field |
907 | 595 |
return field |
892
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
596 |
|
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
597 |
def actual_fields(self, form): |
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
598 |
yield self |
894 | 599 |
format_field = self.get_format_field(form) |
892
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
600 |
if format_field: |
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
601 |
yield format_field |
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
602 |
|
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
603 |
def use_fckeditor(self, form): |
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
604 |
"""return True if fckeditor should be used to edit entity's attribute named |
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
605 |
`attr`, according to user preferences |
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
606 |
""" |
1013
948a3882c94a
add a use_fckeditor method on http request
sylvain.thenault@logilab.fr
parents:
1009
diff
changeset
|
607 |
if form.req.use_fckeditor(): |
1060
d795477ad16b
rename method to form_field_format
sylvain.thenault@logilab.fr
parents:
1059
diff
changeset
|
608 |
return form.form_field_format(self) == 'text/html' |
892
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
609 |
return False |
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
610 |
|
907 | 611 |
def render(self, form, renderer): |
894 | 612 |
format_field = self.get_format_field(form) |
892
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
613 |
if format_field: |
907 | 614 |
result = format_field.render(form, renderer) |
892
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
615 |
else: |
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
616 |
result = u'' |
907 | 617 |
return result + self.get_widget(form).render(form, self) |
618 |
||
619 |
||
620 |
class FileField(StringField): |
|
621 |
widget = FileInput |
|
622 |
needs_multipart = True |
|
623 |
||
624 |
def __init__(self, format_field=None, encoding_field=None, **kwargs): |
|
625 |
super(FileField, self).__init__(**kwargs) |
|
626 |
self.format_field = format_field |
|
627 |
self.encoding_field = encoding_field |
|
628 |
||
629 |
def actual_fields(self, form): |
|
630 |
yield self |
|
631 |
if self.format_field: |
|
632 |
yield self.format_field |
|
633 |
if self.encoding_field: |
|
634 |
yield self.encoding_field |
|
892
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
635 |
|
907 | 636 |
def render(self, form, renderer): |
637 |
wdgs = [self.get_widget(form).render(form, self)] |
|
638 |
if self.format_field or self.encoding_field: |
|
639 |
divid = '%s-advanced' % form.context[self]['name'] |
|
640 |
wdgs.append(u'<a href="%s" title="%s"><img src="%s" alt="%s"/></a>' % |
|
641 |
(html_escape(toggle_action(divid)), |
|
642 |
form.req._('show advanced fields'), |
|
643 |
html_escape(form.req.build_url('data/puce_down.png')), |
|
644 |
form.req._('show advanced fields'))) |
|
645 |
wdgs.append(u'<div id="%s" class="hidden">' % divid) |
|
646 |
if self.format_field: |
|
647 |
wdgs.append(self.render_subfield(form, self.format_field, renderer)) |
|
648 |
if self.encoding_field: |
|
649 |
wdgs.append(self.render_subfield(form, self.encoding_field, renderer)) |
|
650 |
wdgs.append(u'</div>') |
|
651 |
if not self.required and form.context[self]['value']: |
|
652 |
# trick to be able to delete an uploaded file |
|
653 |
wdgs.append(u'<br/>') |
|
654 |
wdgs.append(tags.input(name=u'%s__detach' % form.context[self]['name'], |
|
655 |
type=u'checkbox')) |
|
656 |
wdgs.append(form.req._('detach attached file')) |
|
657 |
return u'\n'.join(wdgs) |
|
658 |
||
659 |
def render_subfield(self, form, field, renderer): |
|
660 |
return (renderer.render_label(form, field) |
|
661 |
+ field.render(form, renderer) |
|
662 |
+ renderer.render_help(form, field) |
|
663 |
+ u'<br/>') |
|
1064 | 664 |
|
907 | 665 |
|
1062 | 666 |
class EditableFileField(FileField): |
667 |
editable_formats = ('text/plain', 'text/html', 'text/rest') |
|
892
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
668 |
|
1062 | 669 |
def render(self, form, renderer): |
670 |
wdgs = [super(EditableFileField, self).render(form, renderer)] |
|
671 |
if form.form_field_format(self) in self.editable_formats: |
|
672 |
data = form.form_field_value(self, {}, load_bytes=True) |
|
673 |
if data: |
|
674 |
encoding = form.form_field_encoding(self) |
|
675 |
try: |
|
676 |
form.context[self]['value'] = unicode(data.getvalue(), encoding) |
|
677 |
form.context[self]['rawvalue'] = form.context[self]['value'] |
|
678 |
except UnicodeError: |
|
679 |
pass |
|
680 |
else: |
|
681 |
if not self.required: |
|
682 |
msg = form.req._( |
|
683 |
'You can either submit a new file using the browse button above' |
|
684 |
', or choose to remove already uploaded file by checking the ' |
|
685 |
'"detach attached file" check-box, or edit file content online ' |
|
686 |
'with the widget below.') |
|
687 |
else: |
|
688 |
msg = form.req._( |
|
689 |
'You can either submit a new file using the browse button above' |
|
690 |
', or edit file content online with the widget below.') |
|
691 |
wdgs.append(u'<p><b>%s</b></p>' % msg) |
|
692 |
wdgs.append(TextArea(setdomid=False).render(form, self)) |
|
693 |
# XXX restore form context? |
|
694 |
return '\n'.join(wdgs) |
|
695 |
||
696 |
||
844 | 697 |
class IntField(Field): |
698 |
def __init__(self, min=None, max=None, **kwargs): |
|
699 |
super(IntField, self).__init__(**kwargs) |
|
700 |
self.min = min |
|
701 |
self.max = max |
|
702 |
||
907 | 703 |
|
903
63a8ab7eeb9c
The value as returned by FieldWidget._render_attrs() is now always a list
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
902
diff
changeset
|
704 |
class BooleanField(Field): |
63a8ab7eeb9c
The value as returned by FieldWidget._render_attrs() is now always a list
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
902
diff
changeset
|
705 |
widget = Radio |
1063
6e55fd09afc4
implement vocabulary for Boolean field
sylvain.thenault@logilab.fr
parents:
1062
diff
changeset
|
706 |
|
6e55fd09afc4
implement vocabulary for Boolean field
sylvain.thenault@logilab.fr
parents:
1062
diff
changeset
|
707 |
def vocabulary(self, form): |
6e55fd09afc4
implement vocabulary for Boolean field
sylvain.thenault@logilab.fr
parents:
1062
diff
changeset
|
708 |
if self.choices: |
6e55fd09afc4
implement vocabulary for Boolean field
sylvain.thenault@logilab.fr
parents:
1062
diff
changeset
|
709 |
return self.choices |
6e55fd09afc4
implement vocabulary for Boolean field
sylvain.thenault@logilab.fr
parents:
1062
diff
changeset
|
710 |
return [(form.req._('yes'), '1'), (form.req._('no'), '')] |
903
63a8ab7eeb9c
The value as returned by FieldWidget._render_attrs() is now always a list
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
902
diff
changeset
|
711 |
|
907 | 712 |
|
864
e0947007542a
basic implementation of Date / Float fields
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
863
diff
changeset
|
713 |
class FloatField(IntField): |
903
63a8ab7eeb9c
The value as returned by FieldWidget._render_attrs() is now always a list
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
902
diff
changeset
|
714 |
def format_single_value(self, req, value): |
864
e0947007542a
basic implementation of Date / Float fields
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
863
diff
changeset
|
715 |
formatstr = entity.req.property_value('ui.float-format') |
e0947007542a
basic implementation of Date / Float fields
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
863
diff
changeset
|
716 |
if value is None: |
e0947007542a
basic implementation of Date / Float fields
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
863
diff
changeset
|
717 |
return u'' |
e0947007542a
basic implementation of Date / Float fields
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
863
diff
changeset
|
718 |
return formatstr % float(value) |
e0947007542a
basic implementation of Date / Float fields
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
863
diff
changeset
|
719 |
|
907 | 720 |
def render_example(self, req): |
721 |
return self.format_value(req, 1.234) |
|
722 |
||
723 |
||
864
e0947007542a
basic implementation of Date / Float fields
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
863
diff
changeset
|
724 |
class DateField(StringField): |
899
48d465b5171a
rename propname into format_prop
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
898
diff
changeset
|
725 |
format_prop = 'ui.date-format' |
905
64fd6eaaa9a4
add needs_css and needs_js on widgets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
904
diff
changeset
|
726 |
widget = DateTimePicker |
844 | 727 |
|
899
48d465b5171a
rename propname into format_prop
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
898
diff
changeset
|
728 |
def format_single_value(self, req, value): |
48d465b5171a
rename propname into format_prop
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
898
diff
changeset
|
729 |
return value and ustrftime(value, req.property_value(self.format_prop)) or u'' |
844 | 730 |
|
907 | 731 |
def render_example(self, req): |
1016
26387b836099
use datetime instead of mx.DateTime
sylvain.thenault@logilab.fr
parents:
1013
diff
changeset
|
732 |
return self.format_value(req, datetime.now()) |
907 | 733 |
|
734 |
||
864
e0947007542a
basic implementation of Date / Float fields
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
863
diff
changeset
|
735 |
class DateTimeField(DateField): |
899
48d465b5171a
rename propname into format_prop
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
898
diff
changeset
|
736 |
format_prop = 'ui.datetime-format' |
864
e0947007542a
basic implementation of Date / Float fields
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
863
diff
changeset
|
737 |
|
907 | 738 |
|
899
48d465b5171a
rename propname into format_prop
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
898
diff
changeset
|
739 |
class TimeField(DateField): |
48d465b5171a
rename propname into format_prop
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
898
diff
changeset
|
740 |
format_prop = 'ui.datetime-format' |
907 | 741 |
|
844 | 742 |
|
863
4fde01fc39ca
restore previous hidden input behaviour (edits- / edito- fields)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
849
diff
changeset
|
743 |
class HiddenInitialValueField(Field): |
4fde01fc39ca
restore previous hidden input behaviour (edits- / edito- fields)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
849
diff
changeset
|
744 |
def __init__(self, visible_field, name): |
4fde01fc39ca
restore previous hidden input behaviour (edits- / edito- fields)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
849
diff
changeset
|
745 |
super(HiddenInitialValueField, self).__init__(name=name, |
898
583f64567256
fix HiddenRelationField bug
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
897
diff
changeset
|
746 |
widget=HiddenInput, |
583f64567256
fix HiddenRelationField bug
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
897
diff
changeset
|
747 |
eidparam=True) |
863
4fde01fc39ca
restore previous hidden input behaviour (edits- / edito- fields)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
849
diff
changeset
|
748 |
self.visible_field = visible_field |
897
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
749 |
|
844 | 750 |
|
863
4fde01fc39ca
restore previous hidden input behaviour (edits- / edito- fields)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
849
diff
changeset
|
751 |
class RelationField(Field): |
903
63a8ab7eeb9c
The value as returned by FieldWidget._render_attrs() is now always a list
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
902
diff
changeset
|
752 |
def __init__(self, **kwargs): |
863
4fde01fc39ca
restore previous hidden input behaviour (edits- / edito- fields)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
849
diff
changeset
|
753 |
super(RelationField, self).__init__(**kwargs) |
897
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
754 |
|
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
755 |
@staticmethod |
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
756 |
def fromcardinality(card, role, **kwargs): |
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
757 |
return RelationField(widget=Select(multiple=card in '*+'), |
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
758 |
**kwargs) |
863
4fde01fc39ca
restore previous hidden input behaviour (edits- / edito- fields)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
849
diff
changeset
|
759 |
|
901
0dcf01eb97a0
implement default vocabulary method on Field, provide a specific one on RelationField
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
900
diff
changeset
|
760 |
def vocabulary(self, form): |
0dcf01eb97a0
implement default vocabulary method on Field, provide a specific one on RelationField
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
900
diff
changeset
|
761 |
entity = form.entity |
0dcf01eb97a0
implement default vocabulary method on Field, provide a specific one on RelationField
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
900
diff
changeset
|
762 |
req = entity.req |
0dcf01eb97a0
implement default vocabulary method on Field, provide a specific one on RelationField
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
900
diff
changeset
|
763 |
# first see if its specified by __linkto form parameters |
0dcf01eb97a0
implement default vocabulary method on Field, provide a specific one on RelationField
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
900
diff
changeset
|
764 |
linkedto = entity.linked_to(self.name, self.role) |
0dcf01eb97a0
implement default vocabulary method on Field, provide a specific one on RelationField
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
900
diff
changeset
|
765 |
if linkedto: |
0dcf01eb97a0
implement default vocabulary method on Field, provide a specific one on RelationField
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
900
diff
changeset
|
766 |
entities = (req.eid_rset(eid).get_entity(0, 0) for eid in linkedto) |
0dcf01eb97a0
implement default vocabulary method on Field, provide a specific one on RelationField
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
900
diff
changeset
|
767 |
return [(entity.view('combobox'), entity.eid) for entity in entities] |
0dcf01eb97a0
implement default vocabulary method on Field, provide a specific one on RelationField
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
900
diff
changeset
|
768 |
# it isn't, check if the entity provides a method to get correct values |
0dcf01eb97a0
implement default vocabulary method on Field, provide a specific one on RelationField
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
900
diff
changeset
|
769 |
res = [] |
0dcf01eb97a0
implement default vocabulary method on Field, provide a specific one on RelationField
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
900
diff
changeset
|
770 |
if not self.required: |
0dcf01eb97a0
implement default vocabulary method on Field, provide a specific one on RelationField
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
900
diff
changeset
|
771 |
res.append(('', INTERNAL_FIELD_VALUE)) |
0dcf01eb97a0
implement default vocabulary method on Field, provide a specific one on RelationField
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
900
diff
changeset
|
772 |
# vocabulary doesn't include current values, add them |
0dcf01eb97a0
implement default vocabulary method on Field, provide a specific one on RelationField
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
900
diff
changeset
|
773 |
if entity.has_eid(): |
0dcf01eb97a0
implement default vocabulary method on Field, provide a specific one on RelationField
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
900
diff
changeset
|
774 |
rset = entity.related(self.name, self.role) |
0dcf01eb97a0
implement default vocabulary method on Field, provide a specific one on RelationField
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
900
diff
changeset
|
775 |
relatedvocab = [(e.view('combobox'), e.eid) for e in rset.entities()] |
0dcf01eb97a0
implement default vocabulary method on Field, provide a specific one on RelationField
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
900
diff
changeset
|
776 |
else: |
0dcf01eb97a0
implement default vocabulary method on Field, provide a specific one on RelationField
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
900
diff
changeset
|
777 |
relatedvocab = [] |
0dcf01eb97a0
implement default vocabulary method on Field, provide a specific one on RelationField
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
900
diff
changeset
|
778 |
return res + form.form_field_vocabulary(self) + relatedvocab |
0dcf01eb97a0
implement default vocabulary method on Field, provide a specific one on RelationField
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
900
diff
changeset
|
779 |
|
0dcf01eb97a0
implement default vocabulary method on Field, provide a specific one on RelationField
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
900
diff
changeset
|
780 |
def format_single_value(self, req, value): |
0dcf01eb97a0
implement default vocabulary method on Field, provide a specific one on RelationField
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
900
diff
changeset
|
781 |
return value |
0dcf01eb97a0
implement default vocabulary method on Field, provide a specific one on RelationField
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
900
diff
changeset
|
782 |
|
844 | 783 |
# forms ############ |
784 |
class metafieldsform(type): |
|
785 |
def __new__(mcs, name, bases, classdict): |
|
786 |
allfields = [] |
|
787 |
for base in bases: |
|
788 |
if hasattr(base, '_fields_'): |
|
789 |
allfields += base._fields_ |
|
790 |
clsfields = (item for item in classdict.items() |
|
791 |
if isinstance(item[1], Field)) |
|
869
168ad6d424d1
form to edit multiple entities, use it in DeleteConfForm
sylvain.thenault@logilab.fr
parents:
867
diff
changeset
|
792 |
for fieldname, field in sorted(clsfields, key=lambda x: x[1].creation_rank): |
844 | 793 |
if not field.name: |
869
168ad6d424d1
form to edit multiple entities, use it in DeleteConfForm
sylvain.thenault@logilab.fr
parents:
867
diff
changeset
|
794 |
field.set_name(fieldname) |
844 | 795 |
allfields.append(field) |
796 |
classdict['_fields_'] = allfields |
|
797 |
return super(metafieldsform, mcs).__new__(mcs, name, bases, classdict) |
|
798 |
||
799 |
||
1047
21d4d5e6aa45
make forms selectable (appobject)
sylvain.thenault@logilab.fr
parents:
1032
diff
changeset
|
800 |
class FieldsForm(FormMixIn, AppObject): |
844 | 801 |
__metaclass__ = metafieldsform |
1047
21d4d5e6aa45
make forms selectable (appobject)
sylvain.thenault@logilab.fr
parents:
1032
diff
changeset
|
802 |
__registry__ = 'forms' |
21d4d5e6aa45
make forms selectable (appobject)
sylvain.thenault@logilab.fr
parents:
1032
diff
changeset
|
803 |
__select__ = yes() |
844 | 804 |
|
1047
21d4d5e6aa45
make forms selectable (appobject)
sylvain.thenault@logilab.fr
parents:
1032
diff
changeset
|
805 |
def __init__(self, req, rset=None, domid=None, title=None, action='edit', |
21d4d5e6aa45
make forms selectable (appobject)
sylvain.thenault@logilab.fr
parents:
1032
diff
changeset
|
806 |
onsubmit="return freezeFormButtons('%(domid)s');", |
869
168ad6d424d1
form to edit multiple entities, use it in DeleteConfForm
sylvain.thenault@logilab.fr
parents:
867
diff
changeset
|
807 |
cssclass=None, cssstyle=None, cwtarget=None, buttons=None, |
168ad6d424d1
form to edit multiple entities, use it in DeleteConfForm
sylvain.thenault@logilab.fr
parents:
867
diff
changeset
|
808 |
redirect_path=None, set_error_url=True, copy_nav_params=False): |
844 | 809 |
self.req = req |
1047
21d4d5e6aa45
make forms selectable (appobject)
sylvain.thenault@logilab.fr
parents:
1032
diff
changeset
|
810 |
self.rset = rset |
892
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
811 |
self.config = req.vreg.config |
887
51e371245bc5
various fixes to have change state and deletion forms working
sylvain.thenault@logilab.fr
parents:
874
diff
changeset
|
812 |
self.domid = domid or 'form' |
844 | 813 |
self.title = title |
814 |
self.action = action |
|
869
168ad6d424d1
form to edit multiple entities, use it in DeleteConfForm
sylvain.thenault@logilab.fr
parents:
867
diff
changeset
|
815 |
self.onsubmit = onsubmit |
168ad6d424d1
form to edit multiple entities, use it in DeleteConfForm
sylvain.thenault@logilab.fr
parents:
867
diff
changeset
|
816 |
self.cssclass = cssclass |
168ad6d424d1
form to edit multiple entities, use it in DeleteConfForm
sylvain.thenault@logilab.fr
parents:
867
diff
changeset
|
817 |
self.cssstyle = cssstyle |
168ad6d424d1
form to edit multiple entities, use it in DeleteConfForm
sylvain.thenault@logilab.fr
parents:
867
diff
changeset
|
818 |
self.cwtarget = cwtarget |
887
51e371245bc5
various fixes to have change state and deletion forms working
sylvain.thenault@logilab.fr
parents:
874
diff
changeset
|
819 |
self.redirect_path = redirect_path |
844 | 820 |
self.fields = list(self.__class__._fields_) |
869
168ad6d424d1
form to edit multiple entities, use it in DeleteConfForm
sylvain.thenault@logilab.fr
parents:
867
diff
changeset
|
821 |
if set_error_url: |
168ad6d424d1
form to edit multiple entities, use it in DeleteConfForm
sylvain.thenault@logilab.fr
parents:
867
diff
changeset
|
822 |
self.form_add_hidden('__errorurl', req.url()) |
168ad6d424d1
form to edit multiple entities, use it in DeleteConfForm
sylvain.thenault@logilab.fr
parents:
867
diff
changeset
|
823 |
if copy_nav_params: |
168ad6d424d1
form to edit multiple entities, use it in DeleteConfForm
sylvain.thenault@logilab.fr
parents:
867
diff
changeset
|
824 |
for param in NAV_FORM_PARAMETERS: |
168ad6d424d1
form to edit multiple entities, use it in DeleteConfForm
sylvain.thenault@logilab.fr
parents:
867
diff
changeset
|
825 |
value = req.form.get(param) |
168ad6d424d1
form to edit multiple entities, use it in DeleteConfForm
sylvain.thenault@logilab.fr
parents:
867
diff
changeset
|
826 |
if value: |
892
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
827 |
self.form_add_hidden(param, initial=value) |
869
168ad6d424d1
form to edit multiple entities, use it in DeleteConfForm
sylvain.thenault@logilab.fr
parents:
867
diff
changeset
|
828 |
self.buttons = buttons or [] |
1053 | 829 |
self.context = None |
1058
c27be37daef8
field_by_name method (on class or instance)
sylvain.thenault@logilab.fr
parents:
1056
diff
changeset
|
830 |
|
c27be37daef8
field_by_name method (on class or instance)
sylvain.thenault@logilab.fr
parents:
1056
diff
changeset
|
831 |
@iclassmethod |
c27be37daef8
field_by_name method (on class or instance)
sylvain.thenault@logilab.fr
parents:
1056
diff
changeset
|
832 |
def field_by_name(cls_or_self, name): |
c27be37daef8
field_by_name method (on class or instance)
sylvain.thenault@logilab.fr
parents:
1056
diff
changeset
|
833 |
if isinstance(cls_or_self, type): |
c27be37daef8
field_by_name method (on class or instance)
sylvain.thenault@logilab.fr
parents:
1056
diff
changeset
|
834 |
fields = cls_or_self._fields_ |
c27be37daef8
field_by_name method (on class or instance)
sylvain.thenault@logilab.fr
parents:
1056
diff
changeset
|
835 |
else: |
c27be37daef8
field_by_name method (on class or instance)
sylvain.thenault@logilab.fr
parents:
1056
diff
changeset
|
836 |
fields = cls_or_self.fields |
c27be37daef8
field_by_name method (on class or instance)
sylvain.thenault@logilab.fr
parents:
1056
diff
changeset
|
837 |
for field in fields: |
c27be37daef8
field_by_name method (on class or instance)
sylvain.thenault@logilab.fr
parents:
1056
diff
changeset
|
838 |
if field.name == name: |
c27be37daef8
field_by_name method (on class or instance)
sylvain.thenault@logilab.fr
parents:
1056
diff
changeset
|
839 |
return field |
c27be37daef8
field_by_name method (on class or instance)
sylvain.thenault@logilab.fr
parents:
1056
diff
changeset
|
840 |
raise Exception('field %s not found' % name) |
c27be37daef8
field_by_name method (on class or instance)
sylvain.thenault@logilab.fr
parents:
1056
diff
changeset
|
841 |
|
844 | 842 |
@property |
847
27c4ebe90d03
prefixed form methods to avoid potential conflicts with field names, button related method, a bit more serious renderer
sylvain.thenault@logilab.fr
parents:
844
diff
changeset
|
843 |
def form_needs_multipart(self): |
844 | 844 |
return any(field.needs_multipart for field in self.fields) |
0 | 845 |
|
869
168ad6d424d1
form to edit multiple entities, use it in DeleteConfForm
sylvain.thenault@logilab.fr
parents:
867
diff
changeset
|
846 |
def form_add_hidden(self, name, value=None, **kwargs): |
903
63a8ab7eeb9c
The value as returned by FieldWidget._render_attrs() is now always a list
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
902
diff
changeset
|
847 |
self.fields.append(StringField(name=name, widget=HiddenInput, |
63a8ab7eeb9c
The value as returned by FieldWidget._render_attrs() is now always a list
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
902
diff
changeset
|
848 |
initial=value, **kwargs)) |
869
168ad6d424d1
form to edit multiple entities, use it in DeleteConfForm
sylvain.thenault@logilab.fr
parents:
867
diff
changeset
|
849 |
|
847
27c4ebe90d03
prefixed form methods to avoid potential conflicts with field names, button related method, a bit more serious renderer
sylvain.thenault@logilab.fr
parents:
844
diff
changeset
|
850 |
def form_render(self, **values): |
844 | 851 |
renderer = values.pop('renderer', FormRenderer()) |
869
168ad6d424d1
form to edit multiple entities, use it in DeleteConfForm
sylvain.thenault@logilab.fr
parents:
867
diff
changeset
|
852 |
return renderer.render(self, values) |
844 | 853 |
|
847
27c4ebe90d03
prefixed form methods to avoid potential conflicts with field names, button related method, a bit more serious renderer
sylvain.thenault@logilab.fr
parents:
844
diff
changeset
|
854 |
def form_build_context(self, values): |
844 | 855 |
self.context = context = {} |
849
8591d896db7e
update some prototype, ChangeStateForm
sylvain.thenault@logilab.fr
parents:
848
diff
changeset
|
856 |
# on validation error, we get a dictionnary of previously submitted values |
8591d896db7e
update some prototype, ChangeStateForm
sylvain.thenault@logilab.fr
parents:
848
diff
changeset
|
857 |
previous_values = self.req.data.get('formvalues') |
8591d896db7e
update some prototype, ChangeStateForm
sylvain.thenault@logilab.fr
parents:
848
diff
changeset
|
858 |
if previous_values: |
8591d896db7e
update some prototype, ChangeStateForm
sylvain.thenault@logilab.fr
parents:
848
diff
changeset
|
859 |
values.update(previous_values) |
847
27c4ebe90d03
prefixed form methods to avoid potential conflicts with field names, button related method, a bit more serious renderer
sylvain.thenault@logilab.fr
parents:
844
diff
changeset
|
860 |
for field in self.fields: |
894 | 861 |
for field in field.actual_fields(self): |
892
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
862 |
value = self.form_field_value(field, values) |
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
863 |
context[field] = {'value': field.format_value(self.req, value), |
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
864 |
'rawvalue': value, |
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
865 |
'name': self.form_field_name(field), |
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
866 |
'id': self.form_field_id(field), |
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
867 |
} |
847
27c4ebe90d03
prefixed form methods to avoid potential conflicts with field names, button related method, a bit more serious renderer
sylvain.thenault@logilab.fr
parents:
844
diff
changeset
|
868 |
|
1061
7d2e6b5fae3c
* new load_bytes argument to form_field_value
sylvain.thenault@logilab.fr
parents:
1060
diff
changeset
|
869 |
def form_field_value(self, field, values, load_bytes=False): |
848
f5aca5c5f6ca
set __errorurl, fix retreiving of field's value
sylvain.thenault@logilab.fr
parents:
847
diff
changeset
|
870 |
"""looks for field's value in |
849
8591d896db7e
update some prototype, ChangeStateForm
sylvain.thenault@logilab.fr
parents:
848
diff
changeset
|
871 |
1. kw args given to render_form (including previously submitted form |
8591d896db7e
update some prototype, ChangeStateForm
sylvain.thenault@logilab.fr
parents:
848
diff
changeset
|
872 |
values if any) |
848
f5aca5c5f6ca
set __errorurl, fix retreiving of field's value
sylvain.thenault@logilab.fr
parents:
847
diff
changeset
|
873 |
2. req.form |
f5aca5c5f6ca
set __errorurl, fix retreiving of field's value
sylvain.thenault@logilab.fr
parents:
847
diff
changeset
|
874 |
3. field's initial value |
f5aca5c5f6ca
set __errorurl, fix retreiving of field's value
sylvain.thenault@logilab.fr
parents:
847
diff
changeset
|
875 |
""" |
f5aca5c5f6ca
set __errorurl, fix retreiving of field's value
sylvain.thenault@logilab.fr
parents:
847
diff
changeset
|
876 |
if field.name in values: |
f5aca5c5f6ca
set __errorurl, fix retreiving of field's value
sylvain.thenault@logilab.fr
parents:
847
diff
changeset
|
877 |
value = values[field.name] |
f5aca5c5f6ca
set __errorurl, fix retreiving of field's value
sylvain.thenault@logilab.fr
parents:
847
diff
changeset
|
878 |
elif field.name in self.req.form: |
f5aca5c5f6ca
set __errorurl, fix retreiving of field's value
sylvain.thenault@logilab.fr
parents:
847
diff
changeset
|
879 |
value = self.req.form[field.name] |
f5aca5c5f6ca
set __errorurl, fix retreiving of field's value
sylvain.thenault@logilab.fr
parents:
847
diff
changeset
|
880 |
else: |
f5aca5c5f6ca
set __errorurl, fix retreiving of field's value
sylvain.thenault@logilab.fr
parents:
847
diff
changeset
|
881 |
value = field.initial |
897
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
882 |
return value |
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
883 |
|
1060
d795477ad16b
rename method to form_field_format
sylvain.thenault@logilab.fr
parents:
1059
diff
changeset
|
884 |
def form_field_format(self, field): |
892
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
885 |
return self.req.property_value('ui.default-text-format') |
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
886 |
|
1061
7d2e6b5fae3c
* new load_bytes argument to form_field_value
sylvain.thenault@logilab.fr
parents:
1060
diff
changeset
|
887 |
def form_field_encoding(self, field): |
7d2e6b5fae3c
* new load_bytes argument to form_field_value
sylvain.thenault@logilab.fr
parents:
1060
diff
changeset
|
888 |
return self.req.encoding |
7d2e6b5fae3c
* new load_bytes argument to form_field_value
sylvain.thenault@logilab.fr
parents:
1060
diff
changeset
|
889 |
|
849
8591d896db7e
update some prototype, ChangeStateForm
sylvain.thenault@logilab.fr
parents:
848
diff
changeset
|
890 |
def form_field_name(self, field): |
847
27c4ebe90d03
prefixed form methods to avoid potential conflicts with field names, button related method, a bit more serious renderer
sylvain.thenault@logilab.fr
parents:
844
diff
changeset
|
891 |
return field.name |
844 | 892 |
|
849
8591d896db7e
update some prototype, ChangeStateForm
sylvain.thenault@logilab.fr
parents:
848
diff
changeset
|
893 |
def form_field_id(self, field): |
847
27c4ebe90d03
prefixed form methods to avoid potential conflicts with field names, button related method, a bit more serious renderer
sylvain.thenault@logilab.fr
parents:
844
diff
changeset
|
894 |
return field.id |
27c4ebe90d03
prefixed form methods to avoid potential conflicts with field names, button related method, a bit more serious renderer
sylvain.thenault@logilab.fr
parents:
844
diff
changeset
|
895 |
|
27c4ebe90d03
prefixed form methods to avoid potential conflicts with field names, button related method, a bit more serious renderer
sylvain.thenault@logilab.fr
parents:
844
diff
changeset
|
896 |
def form_field_vocabulary(self, field): |
844 | 897 |
raise NotImplementedError |
898 |
||
869
168ad6d424d1
form to edit multiple entities, use it in DeleteConfForm
sylvain.thenault@logilab.fr
parents:
867
diff
changeset
|
899 |
def form_buttons(self): |
168ad6d424d1
form to edit multiple entities, use it in DeleteConfForm
sylvain.thenault@logilab.fr
parents:
867
diff
changeset
|
900 |
return self.buttons |
168ad6d424d1
form to edit multiple entities, use it in DeleteConfForm
sylvain.thenault@logilab.fr
parents:
867
diff
changeset
|
901 |
|
168ad6d424d1
form to edit multiple entities, use it in DeleteConfForm
sylvain.thenault@logilab.fr
parents:
867
diff
changeset
|
902 |
|
844 | 903 |
class EntityFieldsForm(FieldsForm): |
1047
21d4d5e6aa45
make forms selectable (appobject)
sylvain.thenault@logilab.fr
parents:
1032
diff
changeset
|
904 |
__select__ = non_final_entity() |
892
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
905 |
|
844 | 906 |
def __init__(self, *args, **kwargs): |
887
51e371245bc5
various fixes to have change state and deletion forms working
sylvain.thenault@logilab.fr
parents:
874
diff
changeset
|
907 |
kwargs.setdefault('domid', 'entityForm') |
869
168ad6d424d1
form to edit multiple entities, use it in DeleteConfForm
sylvain.thenault@logilab.fr
parents:
867
diff
changeset
|
908 |
self.entity = kwargs.pop('entity', None) |
844 | 909 |
super(EntityFieldsForm, self).__init__(*args, **kwargs) |
887
51e371245bc5
various fixes to have change state and deletion forms working
sylvain.thenault@logilab.fr
parents:
874
diff
changeset
|
910 |
self.form_add_hidden('__type', eidparam=True) |
51e371245bc5
various fixes to have change state and deletion forms working
sylvain.thenault@logilab.fr
parents:
874
diff
changeset
|
911 |
self.form_add_hidden('eid') |
844 | 912 |
|
874
90d98d80af82
EntityFieldsForm.form_render() doesn't need entity anymore
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
869
diff
changeset
|
913 |
def form_render(self, **values): |
90d98d80af82
EntityFieldsForm.form_render() doesn't need entity anymore
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
869
diff
changeset
|
914 |
self.form_add_entity_hiddens(self.entity.e_schema) |
869
168ad6d424d1
form to edit multiple entities, use it in DeleteConfForm
sylvain.thenault@logilab.fr
parents:
867
diff
changeset
|
915 |
return super(EntityFieldsForm, self).form_render(**values) |
168ad6d424d1
form to edit multiple entities, use it in DeleteConfForm
sylvain.thenault@logilab.fr
parents:
867
diff
changeset
|
916 |
|
168ad6d424d1
form to edit multiple entities, use it in DeleteConfForm
sylvain.thenault@logilab.fr
parents:
867
diff
changeset
|
917 |
def form_add_entity_hiddens(self, eschema): |
863
4fde01fc39ca
restore previous hidden input behaviour (edits- / edito- fields)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
849
diff
changeset
|
918 |
for field in self.fields[:]: |
894 | 919 |
for field in field.actual_fields(self): |
892
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
920 |
fieldname = field.name |
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
921 |
if fieldname != 'eid' and ( |
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
922 |
(eschema.has_subject_relation(fieldname) or |
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
923 |
eschema.has_object_relation(fieldname))): |
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
924 |
field.eidparam = True |
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
925 |
self.fields.append(self.form_entity_hidden_field(field)) |
863
4fde01fc39ca
restore previous hidden input behaviour (edits- / edito- fields)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
849
diff
changeset
|
926 |
|
869
168ad6d424d1
form to edit multiple entities, use it in DeleteConfForm
sylvain.thenault@logilab.fr
parents:
867
diff
changeset
|
927 |
def form_entity_hidden_field(self, field): |
863
4fde01fc39ca
restore previous hidden input behaviour (edits- / edito- fields)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
849
diff
changeset
|
928 |
"""returns the hidden field which will indicate the value |
4fde01fc39ca
restore previous hidden input behaviour (edits- / edito- fields)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
849
diff
changeset
|
929 |
before the modification |
4fde01fc39ca
restore previous hidden input behaviour (edits- / edito- fields)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
849
diff
changeset
|
930 |
""" |
4fde01fc39ca
restore previous hidden input behaviour (edits- / edito- fields)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
849
diff
changeset
|
931 |
# Only RelationField has a `role` attribute, others are used |
4fde01fc39ca
restore previous hidden input behaviour (edits- / edito- fields)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
849
diff
changeset
|
932 |
# to describe attribute fields => role is 'subject' |
869
168ad6d424d1
form to edit multiple entities, use it in DeleteConfForm
sylvain.thenault@logilab.fr
parents:
867
diff
changeset
|
933 |
if getattr(field, 'role', 'subject') == 'subject': |
863
4fde01fc39ca
restore previous hidden input behaviour (edits- / edito- fields)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
849
diff
changeset
|
934 |
name = 'edits-%s' % field.name |
4fde01fc39ca
restore previous hidden input behaviour (edits- / edito- fields)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
849
diff
changeset
|
935 |
else: |
4fde01fc39ca
restore previous hidden input behaviour (edits- / edito- fields)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
849
diff
changeset
|
936 |
name = 'edito-%s' % field.name |
898
583f64567256
fix HiddenRelationField bug
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
897
diff
changeset
|
937 |
return HiddenInitialValueField(field, name=name) |
869
168ad6d424d1
form to edit multiple entities, use it in DeleteConfForm
sylvain.thenault@logilab.fr
parents:
867
diff
changeset
|
938 |
|
1061
7d2e6b5fae3c
* new load_bytes argument to form_field_value
sylvain.thenault@logilab.fr
parents:
1060
diff
changeset
|
939 |
def form_field_value(self, field, values, load_bytes=False): |
848
f5aca5c5f6ca
set __errorurl, fix retreiving of field's value
sylvain.thenault@logilab.fr
parents:
847
diff
changeset
|
940 |
"""look for field's value with the following rules: |
f5aca5c5f6ca
set __errorurl, fix retreiving of field's value
sylvain.thenault@logilab.fr
parents:
847
diff
changeset
|
941 |
1. handle special __type and eid fields |
849
8591d896db7e
update some prototype, ChangeStateForm
sylvain.thenault@logilab.fr
parents:
848
diff
changeset
|
942 |
2. looks in kw args given to render_form (including previously submitted |
8591d896db7e
update some prototype, ChangeStateForm
sylvain.thenault@logilab.fr
parents:
848
diff
changeset
|
943 |
form values if any) |
848
f5aca5c5f6ca
set __errorurl, fix retreiving of field's value
sylvain.thenault@logilab.fr
parents:
847
diff
changeset
|
944 |
3. looks in req.form |
f5aca5c5f6ca
set __errorurl, fix retreiving of field's value
sylvain.thenault@logilab.fr
parents:
847
diff
changeset
|
945 |
4. if entity has an eid: |
f5aca5c5f6ca
set __errorurl, fix retreiving of field's value
sylvain.thenault@logilab.fr
parents:
847
diff
changeset
|
946 |
1. looks for an associated attribute / method |
f5aca5c5f6ca
set __errorurl, fix retreiving of field's value
sylvain.thenault@logilab.fr
parents:
847
diff
changeset
|
947 |
2. use field's initial value |
f5aca5c5f6ca
set __errorurl, fix retreiving of field's value
sylvain.thenault@logilab.fr
parents:
847
diff
changeset
|
948 |
else: |
f5aca5c5f6ca
set __errorurl, fix retreiving of field's value
sylvain.thenault@logilab.fr
parents:
847
diff
changeset
|
949 |
1. looks for a default_<fieldname> attribute / method on the form |
f5aca5c5f6ca
set __errorurl, fix retreiving of field's value
sylvain.thenault@logilab.fr
parents:
847
diff
changeset
|
950 |
2. use field's initial value |
f5aca5c5f6ca
set __errorurl, fix retreiving of field's value
sylvain.thenault@logilab.fr
parents:
847
diff
changeset
|
951 |
|
f5aca5c5f6ca
set __errorurl, fix retreiving of field's value
sylvain.thenault@logilab.fr
parents:
847
diff
changeset
|
952 |
values found in step 4 may be a callable which'll then be called. |
f5aca5c5f6ca
set __errorurl, fix retreiving of field's value
sylvain.thenault@logilab.fr
parents:
847
diff
changeset
|
953 |
""" |
863
4fde01fc39ca
restore previous hidden input behaviour (edits- / edito- fields)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
849
diff
changeset
|
954 |
fieldname = field.name |
4fde01fc39ca
restore previous hidden input behaviour (edits- / edito- fields)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
849
diff
changeset
|
955 |
if fieldname.startswith('edits-') or fieldname.startswith('edito-'): |
888
603327e9aef4
fix field value for hidden edit[s|Ã ] fields
sylvain.thenault@logilab.fr
parents:
887
diff
changeset
|
956 |
# edit[s|o]- fieds must have the actual value stored on the entity |
603327e9aef4
fix field value for hidden edit[s|Ã ] fields
sylvain.thenault@logilab.fr
parents:
887
diff
changeset
|
957 |
if self.entity.has_eid(): |
1061
7d2e6b5fae3c
* new load_bytes argument to form_field_value
sylvain.thenault@logilab.fr
parents:
1060
diff
changeset
|
958 |
value = self._form_field_entity_value(field.visible_field, |
7d2e6b5fae3c
* new load_bytes argument to form_field_value
sylvain.thenault@logilab.fr
parents:
1060
diff
changeset
|
959 |
default_initial=False) |
888
603327e9aef4
fix field value for hidden edit[s|Ã ] fields
sylvain.thenault@logilab.fr
parents:
887
diff
changeset
|
960 |
else: |
863
4fde01fc39ca
restore previous hidden input behaviour (edits- / edito- fields)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
849
diff
changeset
|
961 |
value = INTERNAL_FIELD_VALUE |
4fde01fc39ca
restore previous hidden input behaviour (edits- / edito- fields)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
849
diff
changeset
|
962 |
elif fieldname == '__type': |
848
f5aca5c5f6ca
set __errorurl, fix retreiving of field's value
sylvain.thenault@logilab.fr
parents:
847
diff
changeset
|
963 |
value = self.entity.id |
863
4fde01fc39ca
restore previous hidden input behaviour (edits- / edito- fields)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
849
diff
changeset
|
964 |
elif fieldname == 'eid': |
848
f5aca5c5f6ca
set __errorurl, fix retreiving of field's value
sylvain.thenault@logilab.fr
parents:
847
diff
changeset
|
965 |
value = self.entity.eid |
863
4fde01fc39ca
restore previous hidden input behaviour (edits- / edito- fields)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
849
diff
changeset
|
966 |
elif fieldname in values: |
4fde01fc39ca
restore previous hidden input behaviour (edits- / edito- fields)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
849
diff
changeset
|
967 |
value = values[fieldname] |
4fde01fc39ca
restore previous hidden input behaviour (edits- / edito- fields)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
849
diff
changeset
|
968 |
elif fieldname in self.req.form: |
4fde01fc39ca
restore previous hidden input behaviour (edits- / edito- fields)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
849
diff
changeset
|
969 |
value = self.req.form[fieldname] |
848
f5aca5c5f6ca
set __errorurl, fix retreiving of field's value
sylvain.thenault@logilab.fr
parents:
847
diff
changeset
|
970 |
else: |
888
603327e9aef4
fix field value for hidden edit[s|Ã ] fields
sylvain.thenault@logilab.fr
parents:
887
diff
changeset
|
971 |
if self.entity.has_eid() and field.eidparam: |
848
f5aca5c5f6ca
set __errorurl, fix retreiving of field's value
sylvain.thenault@logilab.fr
parents:
847
diff
changeset
|
972 |
# use value found on the entity or field's initial value if it's |
f5aca5c5f6ca
set __errorurl, fix retreiving of field's value
sylvain.thenault@logilab.fr
parents:
847
diff
changeset
|
973 |
# not an attribute of the entity (XXX may conflicts and get |
f5aca5c5f6ca
set __errorurl, fix retreiving of field's value
sylvain.thenault@logilab.fr
parents:
847
diff
changeset
|
974 |
# undesired value) |
1061
7d2e6b5fae3c
* new load_bytes argument to form_field_value
sylvain.thenault@logilab.fr
parents:
1060
diff
changeset
|
975 |
value = self._form_field_entity_value(field, default_initial=True, |
7d2e6b5fae3c
* new load_bytes argument to form_field_value
sylvain.thenault@logilab.fr
parents:
1060
diff
changeset
|
976 |
load_bytes=load_bytes) |
848
f5aca5c5f6ca
set __errorurl, fix retreiving of field's value
sylvain.thenault@logilab.fr
parents:
847
diff
changeset
|
977 |
else: |
863
4fde01fc39ca
restore previous hidden input behaviour (edits- / edito- fields)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
849
diff
changeset
|
978 |
defaultattr = 'default_%s' % fieldname |
848
f5aca5c5f6ca
set __errorurl, fix retreiving of field's value
sylvain.thenault@logilab.fr
parents:
847
diff
changeset
|
979 |
if hasattr(self.entity, defaultattr): |
f5aca5c5f6ca
set __errorurl, fix retreiving of field's value
sylvain.thenault@logilab.fr
parents:
847
diff
changeset
|
980 |
# XXX bw compat, default_<field name> on the entity |
f5aca5c5f6ca
set __errorurl, fix retreiving of field's value
sylvain.thenault@logilab.fr
parents:
847
diff
changeset
|
981 |
warn('found %s on %s, should be set on a specific form' |
f5aca5c5f6ca
set __errorurl, fix retreiving of field's value
sylvain.thenault@logilab.fr
parents:
847
diff
changeset
|
982 |
% (defaultattr, self.entity.id), DeprecationWarning) |
f5aca5c5f6ca
set __errorurl, fix retreiving of field's value
sylvain.thenault@logilab.fr
parents:
847
diff
changeset
|
983 |
value = getattr(self.entity, defaultattr) |
f5aca5c5f6ca
set __errorurl, fix retreiving of field's value
sylvain.thenault@logilab.fr
parents:
847
diff
changeset
|
984 |
elif hasattr(self, defaultattr): |
f5aca5c5f6ca
set __errorurl, fix retreiving of field's value
sylvain.thenault@logilab.fr
parents:
847
diff
changeset
|
985 |
# search for default_<field name> on the form instance |
f5aca5c5f6ca
set __errorurl, fix retreiving of field's value
sylvain.thenault@logilab.fr
parents:
847
diff
changeset
|
986 |
value = getattr(self, defaultattr) |
f5aca5c5f6ca
set __errorurl, fix retreiving of field's value
sylvain.thenault@logilab.fr
parents:
847
diff
changeset
|
987 |
else: |
f5aca5c5f6ca
set __errorurl, fix retreiving of field's value
sylvain.thenault@logilab.fr
parents:
847
diff
changeset
|
988 |
# use field's initial value |
f5aca5c5f6ca
set __errorurl, fix retreiving of field's value
sylvain.thenault@logilab.fr
parents:
847
diff
changeset
|
989 |
value = field.initial |
f5aca5c5f6ca
set __errorurl, fix retreiving of field's value
sylvain.thenault@logilab.fr
parents:
847
diff
changeset
|
990 |
if callable(value): |
1059 | 991 |
value = value() |
897
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
992 |
return value |
892
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
993 |
|
1060
d795477ad16b
rename method to form_field_format
sylvain.thenault@logilab.fr
parents:
1059
diff
changeset
|
994 |
def form_field_format(self, field): |
892
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
995 |
entity = self.entity |
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
996 |
if field.eidparam and entity.has_format(field.name) and ( |
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
997 |
entity.has_eid() or '%s_format' % field.name in entity): |
1059 | 998 |
return self.entity.format(field.name) |
892
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
999 |
return self.req.property_value('ui.default-text-format') |
844 | 1000 |
|
1061
7d2e6b5fae3c
* new load_bytes argument to form_field_value
sylvain.thenault@logilab.fr
parents:
1060
diff
changeset
|
1001 |
def form_field_encoding(self, field): |
7d2e6b5fae3c
* new load_bytes argument to form_field_value
sylvain.thenault@logilab.fr
parents:
1060
diff
changeset
|
1002 |
entity = self.entity |
7d2e6b5fae3c
* new load_bytes argument to form_field_value
sylvain.thenault@logilab.fr
parents:
1060
diff
changeset
|
1003 |
if field.eidparam and entity.has_encoding(field.name) and ( |
7d2e6b5fae3c
* new load_bytes argument to form_field_value
sylvain.thenault@logilab.fr
parents:
1060
diff
changeset
|
1004 |
entity.has_eid() or '%s_encoding' % field.name in entity): |
7d2e6b5fae3c
* new load_bytes argument to form_field_value
sylvain.thenault@logilab.fr
parents:
1060
diff
changeset
|
1005 |
return self.entity.text_encoding() |
7d2e6b5fae3c
* new load_bytes argument to form_field_value
sylvain.thenault@logilab.fr
parents:
1060
diff
changeset
|
1006 |
return super(EntityFieldsForm, self).form_field_encoding(field) |
7d2e6b5fae3c
* new load_bytes argument to form_field_value
sylvain.thenault@logilab.fr
parents:
1060
diff
changeset
|
1007 |
|
7d2e6b5fae3c
* new load_bytes argument to form_field_value
sylvain.thenault@logilab.fr
parents:
1060
diff
changeset
|
1008 |
def _form_field_entity_value(self, field, default_initial=True, load_bytes=False): |
888
603327e9aef4
fix field value for hidden edit[s|Ã ] fields
sylvain.thenault@logilab.fr
parents:
887
diff
changeset
|
1009 |
attr = field.name |
603327e9aef4
fix field value for hidden edit[s|Ã ] fields
sylvain.thenault@logilab.fr
parents:
887
diff
changeset
|
1010 |
if field.role == 'object': |
1049
f8e92c2f3bef
fix attribute name for object relation
sylvain.thenault@logilab.fr
parents:
1048
diff
changeset
|
1011 |
attr = 'reverse_' + attr |
907 | 1012 |
else: |
1013 |
attrtype = self.entity.e_schema.destination(attr) |
|
1014 |
if attrtype == 'Password': |
|
1015 |
return self.entity.has_eid() and INTERNAL_FIELD_VALUE or '' |
|
1016 |
if attrtype == 'Bytes': |
|
1061
7d2e6b5fae3c
* new load_bytes argument to form_field_value
sylvain.thenault@logilab.fr
parents:
1060
diff
changeset
|
1017 |
if self.entity.has_eid(): |
7d2e6b5fae3c
* new load_bytes argument to form_field_value
sylvain.thenault@logilab.fr
parents:
1060
diff
changeset
|
1018 |
if load_bytes: |
7d2e6b5fae3c
* new load_bytes argument to form_field_value
sylvain.thenault@logilab.fr
parents:
1060
diff
changeset
|
1019 |
return getattr(self.entity, attr) |
7d2e6b5fae3c
* new load_bytes argument to form_field_value
sylvain.thenault@logilab.fr
parents:
1060
diff
changeset
|
1020 |
# XXX value should reflect if some file is already attached |
7d2e6b5fae3c
* new load_bytes argument to form_field_value
sylvain.thenault@logilab.fr
parents:
1060
diff
changeset
|
1021 |
return True |
7d2e6b5fae3c
* new load_bytes argument to form_field_value
sylvain.thenault@logilab.fr
parents:
1060
diff
changeset
|
1022 |
return False |
888
603327e9aef4
fix field value for hidden edit[s|Ã ] fields
sylvain.thenault@logilab.fr
parents:
887
diff
changeset
|
1023 |
if default_initial: |
903
63a8ab7eeb9c
The value as returned by FieldWidget._render_attrs() is now always a list
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
902
diff
changeset
|
1024 |
value = getattr(self.entity, attr, field.initial) |
888
603327e9aef4
fix field value for hidden edit[s|Ã ] fields
sylvain.thenault@logilab.fr
parents:
887
diff
changeset
|
1025 |
else: |
903
63a8ab7eeb9c
The value as returned by FieldWidget._render_attrs() is now always a list
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
902
diff
changeset
|
1026 |
value = getattr(self.entity, attr) |
63a8ab7eeb9c
The value as returned by FieldWidget._render_attrs() is now always a list
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
902
diff
changeset
|
1027 |
if isinstance(field, RelationField): |
63a8ab7eeb9c
The value as returned by FieldWidget._render_attrs() is now always a list
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
902
diff
changeset
|
1028 |
# in this case, value is the list of related entities |
63a8ab7eeb9c
The value as returned by FieldWidget._render_attrs() is now always a list
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
902
diff
changeset
|
1029 |
value = [ent.eid for ent in value] |
63a8ab7eeb9c
The value as returned by FieldWidget._render_attrs() is now always a list
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
902
diff
changeset
|
1030 |
return value |
63a8ab7eeb9c
The value as returned by FieldWidget._render_attrs() is now always a list
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
902
diff
changeset
|
1031 |
|
849
8591d896db7e
update some prototype, ChangeStateForm
sylvain.thenault@logilab.fr
parents:
848
diff
changeset
|
1032 |
def form_field_name(self, field): |
847
27c4ebe90d03
prefixed form methods to avoid potential conflicts with field names, button related method, a bit more serious renderer
sylvain.thenault@logilab.fr
parents:
844
diff
changeset
|
1033 |
if field.eidparam: |
27c4ebe90d03
prefixed form methods to avoid potential conflicts with field names, button related method, a bit more serious renderer
sylvain.thenault@logilab.fr
parents:
844
diff
changeset
|
1034 |
return eid_param(field.name, self.entity.eid) |
27c4ebe90d03
prefixed form methods to avoid potential conflicts with field names, button related method, a bit more serious renderer
sylvain.thenault@logilab.fr
parents:
844
diff
changeset
|
1035 |
return field.name |
27c4ebe90d03
prefixed form methods to avoid potential conflicts with field names, button related method, a bit more serious renderer
sylvain.thenault@logilab.fr
parents:
844
diff
changeset
|
1036 |
|
849
8591d896db7e
update some prototype, ChangeStateForm
sylvain.thenault@logilab.fr
parents:
848
diff
changeset
|
1037 |
def form_field_id(self, field): |
847
27c4ebe90d03
prefixed form methods to avoid potential conflicts with field names, button related method, a bit more serious renderer
sylvain.thenault@logilab.fr
parents:
844
diff
changeset
|
1038 |
if field.eidparam: |
27c4ebe90d03
prefixed form methods to avoid potential conflicts with field names, button related method, a bit more serious renderer
sylvain.thenault@logilab.fr
parents:
844
diff
changeset
|
1039 |
return eid_param(field.id, self.entity.eid) |
27c4ebe90d03
prefixed form methods to avoid potential conflicts with field names, button related method, a bit more serious renderer
sylvain.thenault@logilab.fr
parents:
844
diff
changeset
|
1040 |
return field.id |
844 | 1041 |
|
1031
1a89683cb687
restore limit on form_field_vocabulary, actually used
sylvain.thenault@logilab.fr
parents:
1016
diff
changeset
|
1042 |
def form_field_vocabulary(self, field, limit=None): |
903
63a8ab7eeb9c
The value as returned by FieldWidget._render_attrs() is now always a list
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
902
diff
changeset
|
1043 |
role, rtype = field.role, field.name |
63a8ab7eeb9c
The value as returned by FieldWidget._render_attrs() is now always a list
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
902
diff
changeset
|
1044 |
try: |
63a8ab7eeb9c
The value as returned by FieldWidget._render_attrs() is now always a list
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
902
diff
changeset
|
1045 |
vocabfunc = getattr(self.entity, '%s_%s_vocabulary' % (role, rtype)) |
63a8ab7eeb9c
The value as returned by FieldWidget._render_attrs() is now always a list
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
902
diff
changeset
|
1046 |
except AttributeError: |
63a8ab7eeb9c
The value as returned by FieldWidget._render_attrs() is now always a list
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
902
diff
changeset
|
1047 |
vocabfunc = getattr(self, '%s_relation_vocabulary' % role) |
63a8ab7eeb9c
The value as returned by FieldWidget._render_attrs() is now always a list
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
902
diff
changeset
|
1048 |
else: |
63a8ab7eeb9c
The value as returned by FieldWidget._render_attrs() is now always a list
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
902
diff
changeset
|
1049 |
# XXX bw compat, default_<field name> on the entity |
63a8ab7eeb9c
The value as returned by FieldWidget._render_attrs() is now always a list
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
902
diff
changeset
|
1050 |
warn('found %s_%s_vocabulary on %s, should be set on a specific form' |
63a8ab7eeb9c
The value as returned by FieldWidget._render_attrs() is now always a list
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
902
diff
changeset
|
1051 |
% (role, rtype, self.entity.id), DeprecationWarning) |
1009 | 1052 |
# NOTE: it is the responsibility of `vocabfunc` to sort the result |
1053 |
# (direclty through RQL or via a python sort). This is also |
|
1054 |
# important because `vocabfunc` might return a list with |
|
1055 |
# couples (label, None) which act as separators. In these |
|
1056 |
# cases, it doesn't make sense to sort results afterwards. |
|
1031
1a89683cb687
restore limit on form_field_vocabulary, actually used
sylvain.thenault@logilab.fr
parents:
1016
diff
changeset
|
1057 |
return vocabfunc(rtype, limit) |
903
63a8ab7eeb9c
The value as returned by FieldWidget._render_attrs() is now always a list
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
902
diff
changeset
|
1058 |
## XXX BACKPORT ME |
63a8ab7eeb9c
The value as returned by FieldWidget._render_attrs() is now always a list
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
902
diff
changeset
|
1059 |
## if self.sort: |
63a8ab7eeb9c
The value as returned by FieldWidget._render_attrs() is now always a list
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
902
diff
changeset
|
1060 |
## choices = sorted(choices) |
63a8ab7eeb9c
The value as returned by FieldWidget._render_attrs() is now always a list
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
902
diff
changeset
|
1061 |
## if self.rschema.rproperty(self.subjtype, self.objtype, 'internationalizable'): |
63a8ab7eeb9c
The value as returned by FieldWidget._render_attrs() is now always a list
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
902
diff
changeset
|
1062 |
## return zip((entity.req._(v) for v in choices), choices) |
844 | 1063 |
|
902
e4de959c76af
vocabulary methods are now defined on forms, not on entities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
901
diff
changeset
|
1064 |
def subject_relation_vocabulary(self, rtype, limit=None): |
e4de959c76af
vocabulary methods are now defined on forms, not on entities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
901
diff
changeset
|
1065 |
"""defaut vocabulary method for the given relation, looking for |
e4de959c76af
vocabulary methods are now defined on forms, not on entities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
901
diff
changeset
|
1066 |
relation's object entities (i.e. self is the subject) |
e4de959c76af
vocabulary methods are now defined on forms, not on entities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
901
diff
changeset
|
1067 |
""" |
e4de959c76af
vocabulary methods are now defined on forms, not on entities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
901
diff
changeset
|
1068 |
entity = self.entity |
e4de959c76af
vocabulary methods are now defined on forms, not on entities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
901
diff
changeset
|
1069 |
if isinstance(rtype, basestring): |
e4de959c76af
vocabulary methods are now defined on forms, not on entities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
901
diff
changeset
|
1070 |
rtype = entity.schema.rschema(rtype) |
e4de959c76af
vocabulary methods are now defined on forms, not on entities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
901
diff
changeset
|
1071 |
done = None |
e4de959c76af
vocabulary methods are now defined on forms, not on entities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
901
diff
changeset
|
1072 |
assert not rtype.is_final(), rtype |
e4de959c76af
vocabulary methods are now defined on forms, not on entities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
901
diff
changeset
|
1073 |
if entity.has_eid(): |
e4de959c76af
vocabulary methods are now defined on forms, not on entities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
901
diff
changeset
|
1074 |
done = set(e.eid for e in getattr(entity, str(rtype))) |
e4de959c76af
vocabulary methods are now defined on forms, not on entities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
901
diff
changeset
|
1075 |
result = [] |
e4de959c76af
vocabulary methods are now defined on forms, not on entities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
901
diff
changeset
|
1076 |
rsetsize = None |
e4de959c76af
vocabulary methods are now defined on forms, not on entities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
901
diff
changeset
|
1077 |
for objtype in rtype.objects(entity.e_schema): |
e4de959c76af
vocabulary methods are now defined on forms, not on entities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
901
diff
changeset
|
1078 |
if limit is not None: |
e4de959c76af
vocabulary methods are now defined on forms, not on entities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
901
diff
changeset
|
1079 |
rsetsize = limit - len(result) |
e4de959c76af
vocabulary methods are now defined on forms, not on entities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
901
diff
changeset
|
1080 |
result += self.relation_vocabulary(rtype, objtype, 'subject', |
e4de959c76af
vocabulary methods are now defined on forms, not on entities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
901
diff
changeset
|
1081 |
rsetsize, done) |
e4de959c76af
vocabulary methods are now defined on forms, not on entities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
901
diff
changeset
|
1082 |
if limit is not None and len(result) >= limit: |
e4de959c76af
vocabulary methods are now defined on forms, not on entities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
901
diff
changeset
|
1083 |
break |
e4de959c76af
vocabulary methods are now defined on forms, not on entities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
901
diff
changeset
|
1084 |
return result |
e4de959c76af
vocabulary methods are now defined on forms, not on entities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
901
diff
changeset
|
1085 |
|
e4de959c76af
vocabulary methods are now defined on forms, not on entities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
901
diff
changeset
|
1086 |
def object_relation_vocabulary(self, rtype, limit=None): |
e4de959c76af
vocabulary methods are now defined on forms, not on entities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
901
diff
changeset
|
1087 |
"""defaut vocabulary method for the given relation, looking for |
e4de959c76af
vocabulary methods are now defined on forms, not on entities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
901
diff
changeset
|
1088 |
relation's subject entities (i.e. self is the object) |
e4de959c76af
vocabulary methods are now defined on forms, not on entities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
901
diff
changeset
|
1089 |
""" |
e4de959c76af
vocabulary methods are now defined on forms, not on entities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
901
diff
changeset
|
1090 |
entity = self.entity |
e4de959c76af
vocabulary methods are now defined on forms, not on entities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
901
diff
changeset
|
1091 |
if isinstance(rtype, basestring): |
e4de959c76af
vocabulary methods are now defined on forms, not on entities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
901
diff
changeset
|
1092 |
rtype = entity.schema.rschema(rtype) |
e4de959c76af
vocabulary methods are now defined on forms, not on entities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
901
diff
changeset
|
1093 |
done = None |
e4de959c76af
vocabulary methods are now defined on forms, not on entities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
901
diff
changeset
|
1094 |
if entity.has_eid(): |
e4de959c76af
vocabulary methods are now defined on forms, not on entities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
901
diff
changeset
|
1095 |
done = set(e.eid for e in getattr(entity, 'reverse_%s' % rtype)) |
e4de959c76af
vocabulary methods are now defined on forms, not on entities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
901
diff
changeset
|
1096 |
result = [] |
e4de959c76af
vocabulary methods are now defined on forms, not on entities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
901
diff
changeset
|
1097 |
rsetsize = None |
e4de959c76af
vocabulary methods are now defined on forms, not on entities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
901
diff
changeset
|
1098 |
for subjtype in rtype.subjects(entity.e_schema): |
e4de959c76af
vocabulary methods are now defined on forms, not on entities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
901
diff
changeset
|
1099 |
if limit is not None: |
e4de959c76af
vocabulary methods are now defined on forms, not on entities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
901
diff
changeset
|
1100 |
rsetsize = limit - len(result) |
e4de959c76af
vocabulary methods are now defined on forms, not on entities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
901
diff
changeset
|
1101 |
result += self.relation_vocabulary(rtype, subjtype, 'object', |
e4de959c76af
vocabulary methods are now defined on forms, not on entities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
901
diff
changeset
|
1102 |
rsetsize, done) |
e4de959c76af
vocabulary methods are now defined on forms, not on entities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
901
diff
changeset
|
1103 |
if limit is not None and len(result) >= limit: |
e4de959c76af
vocabulary methods are now defined on forms, not on entities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
901
diff
changeset
|
1104 |
break |
e4de959c76af
vocabulary methods are now defined on forms, not on entities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
901
diff
changeset
|
1105 |
return result |
e4de959c76af
vocabulary methods are now defined on forms, not on entities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
901
diff
changeset
|
1106 |
|
e4de959c76af
vocabulary methods are now defined on forms, not on entities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
901
diff
changeset
|
1107 |
def relation_vocabulary(self, rtype, targettype, role, |
e4de959c76af
vocabulary methods are now defined on forms, not on entities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
901
diff
changeset
|
1108 |
limit=None, done=None): |
e4de959c76af
vocabulary methods are now defined on forms, not on entities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
901
diff
changeset
|
1109 |
if done is None: |
e4de959c76af
vocabulary methods are now defined on forms, not on entities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
901
diff
changeset
|
1110 |
done = set() |
1009 | 1111 |
rset = self.entity.unrelated(rtype, targettype, role, limit) |
902
e4de959c76af
vocabulary methods are now defined on forms, not on entities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
901
diff
changeset
|
1112 |
res = [] |
e4de959c76af
vocabulary methods are now defined on forms, not on entities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
901
diff
changeset
|
1113 |
for entity in rset.entities(): |
e4de959c76af
vocabulary methods are now defined on forms, not on entities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
901
diff
changeset
|
1114 |
if entity.eid in done: |
e4de959c76af
vocabulary methods are now defined on forms, not on entities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
901
diff
changeset
|
1115 |
continue |
e4de959c76af
vocabulary methods are now defined on forms, not on entities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
901
diff
changeset
|
1116 |
done.add(entity.eid) |
e4de959c76af
vocabulary methods are now defined on forms, not on entities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
901
diff
changeset
|
1117 |
res.append((entity.view('combobox'), entity.eid)) |
e4de959c76af
vocabulary methods are now defined on forms, not on entities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
901
diff
changeset
|
1118 |
return res |
e4de959c76af
vocabulary methods are now defined on forms, not on entities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
901
diff
changeset
|
1119 |
|
869
168ad6d424d1
form to edit multiple entities, use it in DeleteConfForm
sylvain.thenault@logilab.fr
parents:
867
diff
changeset
|
1120 |
|
168ad6d424d1
form to edit multiple entities, use it in DeleteConfForm
sylvain.thenault@logilab.fr
parents:
867
diff
changeset
|
1121 |
class MultipleFieldsForm(FieldsForm): |
168ad6d424d1
form to edit multiple entities, use it in DeleteConfForm
sylvain.thenault@logilab.fr
parents:
867
diff
changeset
|
1122 |
def __init__(self, *args, **kwargs): |
168ad6d424d1
form to edit multiple entities, use it in DeleteConfForm
sylvain.thenault@logilab.fr
parents:
867
diff
changeset
|
1123 |
super(MultipleFieldsForm, self).__init__(*args, **kwargs) |
168ad6d424d1
form to edit multiple entities, use it in DeleteConfForm
sylvain.thenault@logilab.fr
parents:
867
diff
changeset
|
1124 |
self.forms = [] |
168ad6d424d1
form to edit multiple entities, use it in DeleteConfForm
sylvain.thenault@logilab.fr
parents:
867
diff
changeset
|
1125 |
|
168ad6d424d1
form to edit multiple entities, use it in DeleteConfForm
sylvain.thenault@logilab.fr
parents:
867
diff
changeset
|
1126 |
def form_add_subform(self, subform): |
168ad6d424d1
form to edit multiple entities, use it in DeleteConfForm
sylvain.thenault@logilab.fr
parents:
867
diff
changeset
|
1127 |
self.forms.append(subform) |
907 | 1128 |
|
1129 |
||
844 | 1130 |
# form renderers ############ |
1131 |
class FormRenderer(object): |
|
907 | 1132 |
|
1133 |
# renderer interface ###################################################### |
|
847
27c4ebe90d03
prefixed form methods to avoid potential conflicts with field names, button related method, a bit more serious renderer
sylvain.thenault@logilab.fr
parents:
844
diff
changeset
|
1134 |
|
907 | 1135 |
def render(self, form, values, display_help=True): |
844 | 1136 |
data = [] |
1137 |
w = data.append |
|
869
168ad6d424d1
form to edit multiple entities, use it in DeleteConfForm
sylvain.thenault@logilab.fr
parents:
867
diff
changeset
|
1138 |
w(self.open_form(form)) |
896
6e0379fc1988
put form buttons in a separate table
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
894
diff
changeset
|
1139 |
w(u'<div id="progress">%s</div>' % form.req._('validating...')) |
844 | 1140 |
w(u'<fieldset>') |
887
51e371245bc5
various fixes to have change state and deletion forms working
sylvain.thenault@logilab.fr
parents:
874
diff
changeset
|
1141 |
w(tags.input(type='hidden', name='__form_id', value=form.domid)) |
844 | 1142 |
if form.redirect_path: |
887
51e371245bc5
various fixes to have change state and deletion forms working
sylvain.thenault@logilab.fr
parents:
874
diff
changeset
|
1143 |
w(tags.input(type='hidden', name='__redirectpath', value=form.redirect_path)) |
907 | 1144 |
self.render_fields(w, form, values, display_help) |
847
27c4ebe90d03
prefixed form methods to avoid potential conflicts with field names, button related method, a bit more serious renderer
sylvain.thenault@logilab.fr
parents:
844
diff
changeset
|
1145 |
self.render_buttons(w, form) |
844 | 1146 |
w(u'</fieldset>') |
1147 |
w(u'</form>') |
|
1148 |
return '\n'.join(data) |
|
907 | 1149 |
|
1150 |
def render_label(self, form, field): |
|
1151 |
label = form.req._(field.label) |
|
1152 |
attrs = {'for': form.context[field]['id']} |
|
1153 |
if field.required: |
|
1154 |
attrs['class'] = 'required' |
|
1155 |
return tags.label(label, **attrs) |
|
847
27c4ebe90d03
prefixed form methods to avoid potential conflicts with field names, button related method, a bit more serious renderer
sylvain.thenault@logilab.fr
parents:
844
diff
changeset
|
1156 |
|
907 | 1157 |
def render_help(self, form, field): |
1158 |
help = [ u'<br/>' ] |
|
1159 |
descr = field.help |
|
1160 |
if descr: |
|
1161 |
help.append('<span class="helper">%s</span>' % req._(descr)) |
|
1162 |
example = field.example_format(form.req) |
|
1163 |
if example: |
|
1164 |
help.append('<span class="helper">(%s: %s)</span>' |
|
1165 |
% (req._('sample format'), example)) |
|
1166 |
return u' '.join(help) |
|
1167 |
||
1168 |
# specific methods (mostly to ease overriding) ############################# |
|
1169 |
||
869
168ad6d424d1
form to edit multiple entities, use it in DeleteConfForm
sylvain.thenault@logilab.fr
parents:
867
diff
changeset
|
1170 |
def open_form(self, form): |
168ad6d424d1
form to edit multiple entities, use it in DeleteConfForm
sylvain.thenault@logilab.fr
parents:
867
diff
changeset
|
1171 |
if form.form_needs_multipart: |
168ad6d424d1
form to edit multiple entities, use it in DeleteConfForm
sylvain.thenault@logilab.fr
parents:
867
diff
changeset
|
1172 |
enctype = 'multipart/form-data' |
168ad6d424d1
form to edit multiple entities, use it in DeleteConfForm
sylvain.thenault@logilab.fr
parents:
867
diff
changeset
|
1173 |
else: |
168ad6d424d1
form to edit multiple entities, use it in DeleteConfForm
sylvain.thenault@logilab.fr
parents:
867
diff
changeset
|
1174 |
enctype = 'application/x-www-form-urlencoded' |
1009 | 1175 |
tag = ('<form action="%s" method="post" id="%s" enctype="%s"' % ( |
887
51e371245bc5
various fixes to have change state and deletion forms working
sylvain.thenault@logilab.fr
parents:
874
diff
changeset
|
1176 |
html_escape(form.action or '#'), form.domid, enctype)) |
869
168ad6d424d1
form to edit multiple entities, use it in DeleteConfForm
sylvain.thenault@logilab.fr
parents:
867
diff
changeset
|
1177 |
if form.onsubmit: |
1050
c9815bef16d7
expand onsubmit using form's __dict__
sylvain.thenault@logilab.fr
parents:
1049
diff
changeset
|
1178 |
tag += ' onsubmit="%s"' % html_escape(form.onsubmit % form.__dict__) |
869
168ad6d424d1
form to edit multiple entities, use it in DeleteConfForm
sylvain.thenault@logilab.fr
parents:
867
diff
changeset
|
1179 |
if form.cssstyle: |
168ad6d424d1
form to edit multiple entities, use it in DeleteConfForm
sylvain.thenault@logilab.fr
parents:
867
diff
changeset
|
1180 |
tag += ' style="%s"' % html_escape(form.cssstyle) |
168ad6d424d1
form to edit multiple entities, use it in DeleteConfForm
sylvain.thenault@logilab.fr
parents:
867
diff
changeset
|
1181 |
if form.cssclass: |
168ad6d424d1
form to edit multiple entities, use it in DeleteConfForm
sylvain.thenault@logilab.fr
parents:
867
diff
changeset
|
1182 |
tag += ' class="%s"' % html_escape(form.cssclass) |
168ad6d424d1
form to edit multiple entities, use it in DeleteConfForm
sylvain.thenault@logilab.fr
parents:
867
diff
changeset
|
1183 |
if form.cwtarget: |
168ad6d424d1
form to edit multiple entities, use it in DeleteConfForm
sylvain.thenault@logilab.fr
parents:
867
diff
changeset
|
1184 |
tag += ' cubicweb:target="%s"' % html_escape(form.cwtarget) |
168ad6d424d1
form to edit multiple entities, use it in DeleteConfForm
sylvain.thenault@logilab.fr
parents:
867
diff
changeset
|
1185 |
return tag + '>' |
168ad6d424d1
form to edit multiple entities, use it in DeleteConfForm
sylvain.thenault@logilab.fr
parents:
867
diff
changeset
|
1186 |
|
907 | 1187 |
def render_fields(self, w, form, values, display_help=True): |
869
168ad6d424d1
form to edit multiple entities, use it in DeleteConfForm
sylvain.thenault@logilab.fr
parents:
867
diff
changeset
|
1188 |
form.form_build_context(values) |
863
4fde01fc39ca
restore previous hidden input behaviour (edits- / edito- fields)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
849
diff
changeset
|
1189 |
fields = form.fields[:] |
4fde01fc39ca
restore previous hidden input behaviour (edits- / edito- fields)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
849
diff
changeset
|
1190 |
for field in form.fields: |
892
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
1191 |
if not field.is_visible(): |
907 | 1192 |
w(field.render(form, self)) |
863
4fde01fc39ca
restore previous hidden input behaviour (edits- / edito- fields)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
849
diff
changeset
|
1193 |
fields.remove(field) |
869
168ad6d424d1
form to edit multiple entities, use it in DeleteConfForm
sylvain.thenault@logilab.fr
parents:
867
diff
changeset
|
1194 |
if fields: |
168ad6d424d1
form to edit multiple entities, use it in DeleteConfForm
sylvain.thenault@logilab.fr
parents:
867
diff
changeset
|
1195 |
w(u'<table>') |
168ad6d424d1
form to edit multiple entities, use it in DeleteConfForm
sylvain.thenault@logilab.fr
parents:
867
diff
changeset
|
1196 |
for field in fields: |
168ad6d424d1
form to edit multiple entities, use it in DeleteConfForm
sylvain.thenault@logilab.fr
parents:
867
diff
changeset
|
1197 |
w(u'<tr>') |
168ad6d424d1
form to edit multiple entities, use it in DeleteConfForm
sylvain.thenault@logilab.fr
parents:
867
diff
changeset
|
1198 |
w('<th>%s</th>' % self.render_label(form, field)) |
168ad6d424d1
form to edit multiple entities, use it in DeleteConfForm
sylvain.thenault@logilab.fr
parents:
867
diff
changeset
|
1199 |
w(u'<td style="width:100%;">') |
907 | 1200 |
w(field.render(form, self)) |
1201 |
if display_help == True: |
|
1202 |
w(self.render_help(form, field)) |
|
869
168ad6d424d1
form to edit multiple entities, use it in DeleteConfForm
sylvain.thenault@logilab.fr
parents:
867
diff
changeset
|
1203 |
w(u'</td></tr>') |
168ad6d424d1
form to edit multiple entities, use it in DeleteConfForm
sylvain.thenault@logilab.fr
parents:
867
diff
changeset
|
1204 |
w(u'</table>') |
168ad6d424d1
form to edit multiple entities, use it in DeleteConfForm
sylvain.thenault@logilab.fr
parents:
867
diff
changeset
|
1205 |
for childform in getattr(form, 'forms', []): |
168ad6d424d1
form to edit multiple entities, use it in DeleteConfForm
sylvain.thenault@logilab.fr
parents:
867
diff
changeset
|
1206 |
self.render_fields(w, childform, values) |
892
1558772340a7
rich field / fckeditor handling
sylvain.thenault@logilab.fr
parents:
888
diff
changeset
|
1207 |
|
847
27c4ebe90d03
prefixed form methods to avoid potential conflicts with field names, button related method, a bit more serious renderer
sylvain.thenault@logilab.fr
parents:
844
diff
changeset
|
1208 |
def render_buttons(self, w, form): |
896
6e0379fc1988
put form buttons in a separate table
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
894
diff
changeset
|
1209 |
w(u'<table class="formButtonBar">\n<tr>\n') |
869
168ad6d424d1
form to edit multiple entities, use it in DeleteConfForm
sylvain.thenault@logilab.fr
parents:
867
diff
changeset
|
1210 |
for button in form.form_buttons(): |
896
6e0379fc1988
put form buttons in a separate table
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
894
diff
changeset
|
1211 |
w(u'<td>%s</td>\n' % button) |
6e0379fc1988
put form buttons in a separate table
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
894
diff
changeset
|
1212 |
w(u'</tr></table>') |
897
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
1213 |
|
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
1214 |
|
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
1215 |
def stringfield_from_constraints(constraints, **kwargs): |
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
1216 |
field = None |
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
1217 |
for cstr in constraints: |
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
1218 |
if isinstance(cstr, StaticVocabularyConstraint): |
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
1219 |
return StringField(widget=Select(vocabulary=cstr.vocabulary), |
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
1220 |
**kwargs) |
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
1221 |
if isinstance(cstr, SizeConstraint) and cstr.max is not None: |
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
1222 |
if cstr.max > 257: |
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
1223 |
field = textfield_from_constraint(cstr, **kwargs) |
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
1224 |
else: |
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
1225 |
field = StringField(max_length=cstr.max, **kwargs) |
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
1226 |
return field or TextField(**kwargs) |
847
27c4ebe90d03
prefixed form methods to avoid potential conflicts with field names, button related method, a bit more serious renderer
sylvain.thenault@logilab.fr
parents:
844
diff
changeset
|
1227 |
|
897
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
1228 |
|
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
1229 |
def textfield_from_constraint(constraint, **kwargs): |
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
1230 |
if 256 < constraint.max < 513: |
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
1231 |
rows, cols = 5, 60 |
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
1232 |
else: |
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
1233 |
rows, cols = 10, 80 |
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
1234 |
return TextField(rows, cols, **kwargs) |
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
1235 |
|
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
1236 |
|
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
1237 |
def find_field(eclass, subjschema, rschema, role='subject'): |
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
1238 |
"""return the most adapated widget to edit the relation |
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
1239 |
'subjschema rschema objschema' according to information found in the schema |
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
1240 |
""" |
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
1241 |
fieldclass = None |
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
1242 |
if role == 'subject': |
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
1243 |
objschema = rschema.objects(subjschema)[0] |
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
1244 |
cardidx = 0 |
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
1245 |
else: |
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
1246 |
objschema = rschema.subjects(subjschema)[0] |
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
1247 |
cardidx = 1 |
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
1248 |
card = rschema.rproperty(subjschema, objschema, 'cardinality')[cardidx] |
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
1249 |
required = card in '1+' |
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
1250 |
if rschema in eclass.widgets: |
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
1251 |
fieldclass = eclass.widgets[rschema] |
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
1252 |
if isinstance(fieldclass, basestring): |
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
1253 |
return StringField(name=rschema.type) |
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
1254 |
elif not rschema.is_final(): |
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
1255 |
return RelationField.fromcardinality(card, role,name=rschema.type, |
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
1256 |
required=required) |
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
1257 |
else: |
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
1258 |
fieldclass = FIELDS[objschema] |
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
1259 |
if fieldclass is StringField: |
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
1260 |
constraints = rschema.rproperty(subjschema, objschema, 'constraints') |
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
1261 |
return stringfield_from_constraints(constraints, name=rschema.type, |
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
1262 |
required=required) |
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
1263 |
return fieldclass(name=rschema.type, required=required) |
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
1264 |
|
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
1265 |
FIELDS = { |
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
1266 |
'Boolean': BooleanField, |
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
1267 |
'Bytes': FileField, |
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
1268 |
'Date': DateField, |
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
1269 |
'Datetime': DateTimeField, |
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
1270 |
'Int': IntField, |
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
1271 |
'Float': FloatField, |
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
1272 |
'Decimal': StringField, |
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
1273 |
'Password': StringField, |
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
1274 |
'String' : StringField, |
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
1275 |
'Time': TimeField, |
f5b91f11d8b6
provide basic methods to build fields from schema constraints / cardinality
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
896
diff
changeset
|
1276 |
} |