17 from cubicweb.view import NOINDEX, NOFOLLOW, View, EntityView, AnyRsetView |
17 from cubicweb.view import NOINDEX, NOFOLLOW, View, EntityView, AnyRsetView |
18 from cubicweb.common.registerers import accepts_registerer |
18 from cubicweb.common.registerers import accepts_registerer |
19 from cubicweb.web import stdmsgs |
19 from cubicweb.web import stdmsgs |
20 from cubicweb.web.httpcache import NoHTTPCacheManager |
20 from cubicweb.web.httpcache import NoHTTPCacheManager |
21 from cubicweb.web.controller import redirect_params |
21 from cubicweb.web.controller import redirect_params |
22 from cubicweb.web import eid_param |
22 from cubicweb.web import INTERNAL_FIELD_VALUE, eid_param |
|
23 |
23 |
24 |
24 |
25 |
25 def relation_id(eid, rtype, target, reid): |
26 def relation_id(eid, rtype, target, reid): |
26 if target == 'subject': |
27 if target == 'subject': |
27 return u'%s:%s:%s' % (eid, rtype, reid) |
28 return u'%s:%s:%s' % (eid, rtype, reid) |
218 label = self.req._(label or stdmsgs.BUTTON_OK).capitalize() |
219 label = self.req._(label or stdmsgs.BUTTON_OK).capitalize() |
219 return self.BUTTON_STR % ('defaultsubmit', label, tabindex or 2) |
220 return self.BUTTON_STR % ('defaultsubmit', label, tabindex or 2) |
220 |
221 |
221 def button_apply(self, label=None, tabindex=None): |
222 def button_apply(self, label=None, tabindex=None): |
222 label = self.req._(label or stdmsgs.BUTTON_APPLY).capitalize() |
223 label = self.req._(label or stdmsgs.BUTTON_APPLY).capitalize() |
223 return self.ACTION_SUBMIT_STR % ('__action_apply', label, self.domid, label, tabindex or 3) |
224 return self.ACTION_SUBMIT_STR % ('__action_apply', label, self.domid, |
|
225 label, tabindex or 3) |
224 |
226 |
225 def button_delete(self, label=None, tabindex=None): |
227 def button_delete(self, label=None, tabindex=None): |
226 label = self.req._(label or stdmsgs.BUTTON_DELETE).capitalize() |
228 label = self.req._(label or stdmsgs.BUTTON_DELETE).capitalize() |
227 return self.ACTION_SUBMIT_STR % ('__action_delete', label, self.domid, label, tabindex or 3) |
229 return self.ACTION_SUBMIT_STR % ('__action_delete', label, self.domid, |
|
230 label, tabindex or 3) |
228 |
231 |
229 def button_cancel(self, label=None, tabindex=None): |
232 def button_cancel(self, label=None, tabindex=None): |
230 label = self.req._(label or stdmsgs.BUTTON_CANCEL).capitalize() |
233 label = self.req._(label or stdmsgs.BUTTON_CANCEL).capitalize() |
231 return self.ACTION_SUBMIT_STR % ('__action_cancel', label, self.domid, label, tabindex or 4) |
234 return self.ACTION_SUBMIT_STR % ('__action_cancel', label, self.domid, |
|
235 label, tabindex or 4) |
232 |
236 |
233 def button_reset(self, label=None, tabindex=None): |
237 def button_reset(self, label=None, tabindex=None): |
234 label = self.req._(label or stdmsgs.BUTTON_CANCEL).capitalize() |
238 label = self.req._(label or stdmsgs.BUTTON_CANCEL).capitalize() |
235 return u'<input class="validateButton" type="reset" value="%s" tabindex="%s"/>' % ( |
239 return u'<input class="validateButton" type="reset" value="%s" tabindex="%s"/>' % ( |
236 label, tabindex or 4) |
240 label, tabindex or 4) |
382 class DateField(IntField): |
386 class DateField(IntField): |
383 |
387 |
384 def format_value(self, req, value): |
388 def format_value(self, req, value): |
385 return value and ustrftime(value, req.property_value('ui.date-format')) or u'' |
389 return value and ustrftime(value, req.property_value('ui.date-format')) or u'' |
386 |
390 |
387 class DateTimeField(IntField): |
391 class HiddenInitialValueField(Field): |
388 |
392 def __init__(self, visible_field, name): |
389 def format_value(self, req, value): |
393 super(HiddenInitialValueField, self).__init__(name=name, |
390 return value and ustrftime(value, req.property_value('ui.datetime-format')) or u'' |
394 widget=HiddenInput) |
391 |
395 self.visible_field = visible_field |
392 class FileField(IntField): |
|
393 needs_multipart = True |
|
394 |
396 |
|
397 class RelationField(Field): |
|
398 def __init__(self, role='subject', **kwargs): |
|
399 super(RelationField, self).__init__(**kwargs) |
|
400 self.role = role |
|
401 |
395 # forms ############ |
402 # forms ############ |
396 class metafieldsform(type): |
403 class metafieldsform(type): |
397 def __new__(mcs, name, bases, classdict): |
404 def __new__(mcs, name, bases, classdict): |
398 allfields = [] |
405 allfields = [] |
399 for base in bases: |
406 for base in bases: |
438 # on validation error, we get a dictionnary of previously submitted values |
445 # on validation error, we get a dictionnary of previously submitted values |
439 previous_values = self.req.data.get('formvalues') |
446 previous_values = self.req.data.get('formvalues') |
440 if previous_values: |
447 if previous_values: |
441 values.update(previous_values) |
448 values.update(previous_values) |
442 for field in self.fields: |
449 for field in self.fields: |
443 context[field] = {'value': self.form_field_value(field, field_values), |
450 context[field] = {'value': self.form_field_value(field, values), |
444 'name': self.form_field_name(field), |
451 'name': self.form_field_name(field), |
445 'id': self.form_field_id(field), |
452 'id': self.form_field_id(field), |
446 } |
453 } |
447 |
454 |
448 def form_field_value(self, field, values): |
455 def form_field_value(self, field, values): |
501 self.fields.append(TextField(name='__type', widget=HiddenInput)) |
508 self.fields.append(TextField(name='__type', widget=HiddenInput)) |
502 self.fields.append(TextField(name='eid', widget=HiddenInput)) |
509 self.fields.append(TextField(name='eid', widget=HiddenInput)) |
503 |
510 |
504 def form_render(self, entity, **values): |
511 def form_render(self, entity, **values): |
505 self.entity = entity |
512 self.entity = entity |
|
513 eschema = self.entity.e_schema |
|
514 for field in self.fields[:]: |
|
515 fieldname = field.name |
|
516 if fieldname != 'eid' and ( |
|
517 (eschema.has_subject_relation(fieldname) or |
|
518 eschema.has_object_relation(fieldname))): |
|
519 self.fields.append(self.build_hidden_field(field)) |
506 return super(EntityFieldsForm, self).form_render(**values) |
520 return super(EntityFieldsForm, self).form_render(**values) |
507 |
521 |
|
522 def build_hidden_field(self, field): |
|
523 """returns the hidden field which will indicate the value |
|
524 before the modification |
|
525 """ |
|
526 # Only RelationField has a `role` attribute, others are used |
|
527 # to describe attribute fields => role is 'subject' |
|
528 role = getattr(field, 'role', 'subject') |
|
529 if role == 'subject': |
|
530 name = 'edits-%s' % field.name |
|
531 else: |
|
532 name = 'edito-%s' % field.name |
|
533 return HiddenInitialValueField(field, name=name) |
|
534 |
508 def form_field_value(self, field, values): |
535 def form_field_value(self, field, values): |
509 """look for field's value with the following rules: |
536 """look for field's value with the following rules: |
510 1. handle special __type and eid fields |
537 1. handle special __type and eid fields |
511 2. looks in kw args given to render_form (including previously submitted |
538 2. looks in kw args given to render_form (including previously submitted |
512 form values if any) |
539 form values if any) |
518 1. looks for a default_<fieldname> attribute / method on the form |
545 1. looks for a default_<fieldname> attribute / method on the form |
519 2. use field's initial value |
546 2. use field's initial value |
520 |
547 |
521 values found in step 4 may be a callable which'll then be called. |
548 values found in step 4 may be a callable which'll then be called. |
522 """ |
549 """ |
523 if field.name == '__type': |
550 fieldname = field.name |
|
551 if fieldname.startswith('edits-') or fieldname.startswith('edito-'): |
|
552 value = self.form_field_value(field.visible_field, values) |
|
553 if value is None or not self.entity.has_eid(): |
|
554 value = INTERNAL_FIELD_VALUE |
|
555 elif fieldname == '__type': |
524 value = self.entity.id |
556 value = self.entity.id |
525 elif field.name == 'eid': |
557 elif fieldname == 'eid': |
526 value = self.entity.eid |
558 value = self.entity.eid |
527 elif field.name in values: |
559 elif fieldname in values: |
528 value = values[field.name] |
560 value = values[fieldname] |
529 elif field.name in self.req.form: |
561 elif fieldname in self.req.form: |
530 value = self.req.form[field.name] |
562 value = self.req.form[fieldname] |
531 else: |
563 else: |
532 if self.entity.has_eid(): |
564 if self.entity.has_eid(): |
533 # use value found on the entity or field's initial value if it's |
565 # use value found on the entity or field's initial value if it's |
534 # not an attribute of the entity (XXX may conflicts and get |
566 # not an attribute of the entity (XXX may conflicts and get |
535 # undesired value) |
567 # undesired value) |
536 value = getattr(self.entity, field.name, field.initial) |
568 value = getattr(self.entity, fieldname, field.initial) |
537 else: |
569 else: |
538 defaultattr = 'default_%s' % field.name |
570 defaultattr = 'default_%s' % fieldname |
539 if hasattr(self.entity, defaultattr): |
571 if hasattr(self.entity, defaultattr): |
540 # XXX bw compat, default_<field name> on the entity |
572 # XXX bw compat, default_<field name> on the entity |
541 warn('found %s on %s, should be set on a specific form' |
573 warn('found %s on %s, should be set on a specific form' |
542 % (defaultattr, self.entity.id), DeprecationWarning) |
574 % (defaultattr, self.entity.id), DeprecationWarning) |
543 value = getattr(self.entity, defaultattr) |
575 value = getattr(self.entity, defaultattr) |
590 w(u'</fieldset>') |
622 w(u'</fieldset>') |
591 w(u'</form>') |
623 w(u'</form>') |
592 return '\n'.join(data) |
624 return '\n'.join(data) |
593 |
625 |
594 def render_fields(self, w, form): |
626 def render_fields(self, w, form): |
|
627 fields = form.fields[:] |
|
628 for field in form.fields: |
|
629 if isinstance(field.widget, HiddenInput): |
|
630 w(field.render(form)) |
|
631 fields.remove(field) |
595 w(u'<table>') |
632 w(u'<table>') |
596 for field in form.fields: |
633 for field in fields: |
597 w(u'<tr>') |
634 w(u'<tr>') |
598 w('<th>%s</th>' % self.render_label(form, field)) |
635 w('<th>%s</th>' % self.render_label(form, field)) |
599 w(u'<td style="width:100%;">') |
636 w(u'<td style="width:100%;">') |
600 w(field.render(form)) |
637 w(field.render(form)) |
601 w(u'</td></tr>') |
638 w(u'</td></tr>') |