web/views/reledit.py
branchstable
changeset 6246 62e25fac41cd
parent 6111 06c96a79c3c0
child 6264 0dcd19d89767
equal deleted inserted replaced
6245:e7e9d73d0c07 6246:62e25fac41cd
    19 """
    19 """
    20 
    20 
    21 import copy
    21 import copy
    22 
    22 
    23 from logilab.mtconverter import xml_escape
    23 from logilab.mtconverter import xml_escape
       
    24 from logilab.common.deprecation import deprecated
    24 
    25 
    25 from cubicweb import neg_role
    26 from cubicweb import neg_role
    26 from cubicweb.schema import display_name
    27 from cubicweb.schema import display_name
    27 from cubicweb.utils import json_dumps
    28 from cubicweb.utils import json_dumps
    28 from cubicweb.selectors import non_final_entity, match_kwargs
    29 from cubicweb.selectors import non_final_entity, match_kwargs
    37         return u''
    38         return u''
    38     def render(self, *_args, **_kwargs):
    39     def render(self, *_args, **_kwargs):
    39         return u''
    40         return u''
    40     def append_field(self, *args):
    41     def append_field(self, *args):
    41         pass
    42         pass
    42     def field_by_name(self, rtype, role, eschema=None):
    43 
    43         return None
    44 rctrl = uicfg.reledit_ctrl
    44 
    45 
    45 class ClickAndEditFormView(EntityView):
    46 class ClickAndEditFormView(EntityView):
    46     __regid__ = 'doreledit'
    47     __regid__ = 'doreledit'
    47     __select__ = non_final_entity() & match_kwargs('rtype')
    48     __select__ = non_final_entity() & match_kwargs('rtype')
    48 
    49 
    58     _deletemsg = _('click to delete this value')
    59     _deletemsg = _('click to delete this value')
    59     _editzone = u'<img title="%(msg)s" src="data/pen_icon.png" alt="%(msg)s"/>'
    60     _editzone = u'<img title="%(msg)s" src="data/pen_icon.png" alt="%(msg)s"/>'
    60     _editzonemsg = _('click to edit this field')
    61     _editzonemsg = _('click to edit this field')
    61 
    62 
    62     # default relation vids according to cardinality
    63     # default relation vids according to cardinality
       
    64     # can be changed per rtype using reledit_ctrl rtag
    63     _one_rvid = 'incontext'
    65     _one_rvid = 'incontext'
    64     _many_rvid = 'csv'
    66     _many_rvid = 'csv'
       
    67     # renderer
       
    68     _form_renderer_id = 'base'
    65 
    69 
    66     def cell_call(self, row, col, rtype=None, role='subject',
    70     def cell_call(self, row, col, rtype=None, role='subject',
    67                   reload=False, # controls reloading the whole page after change
    71                   reload=False, # controls reloading the whole page after change
    68                                 # boolean, eid (to redirect), or
    72                                 # boolean, eid (to redirect), or
    69                                 # function taking the subject entity & returning a boolean or an eid
    73                                 # function taking the subject entity & returning a boolean or an eid
    70                   rvid=None,    # vid to be applied to other side of rtype (non final relations only)
    74                   rvid=None,    # vid to be applied to other side of rtype (non final relations only)
    71                   default_value=None,
    75                   default_value=None,
    72                   formid=None
    76                   formid='base'
    73                   ):
    77                   ):
    74         """display field to edit entity's `rtype` relation on click"""
    78         """display field to edit entity's `rtype` relation on click"""
    75         assert rtype
    79         assert rtype
    76         assert role in ('subject', 'object'), '%s is not an acceptable role value' % role
    80         assert role in ('subject', 'object'), '%s is not an acceptable role value' % role
    77         if self.__regid__ == 'doreledit':
       
    78             assert formid
       
    79         self._cw.add_js('cubicweb.reledit.js')
       
    80         if formid:
       
    81             self._cw.add_js('cubicweb.edition.js')
       
    82         self._cw.add_css('cubicweb.form.css')
    81         self._cw.add_css('cubicweb.form.css')
       
    82         self._cw.add_js('cubicweb.reledit.js', 'cubicweb.edition.js')
    83         entity = self.cw_rset.get_entity(row, col)
    83         entity = self.cw_rset.get_entity(row, col)
    84         rschema = self._cw.vreg.schema[rtype]
    84         rschema = self._cw.vreg.schema[rtype]
       
    85         self._rules = rctrl.etype_get(entity.e_schema.type, rschema.type, role, '*')
    85         reload = self._compute_reload(entity, rschema, role, reload)
    86         reload = self._compute_reload(entity, rschema, role, reload)
    86         default_value = self._compute_default_value(entity, rschema, role, default_value)
    87         default_value = self._compute_default_value(entity, rschema, role, default_value)
    87         divid = self._build_divid(rtype, role, entity.eid)
    88         divid = self._build_divid(rtype, role, entity.eid)
    88         if rschema.final:
    89         if rschema.final:
    89             self._handle_attributes(entity, rschema, role, divid, reload, default_value)
    90             self._handle_attribute(entity, rschema, role, divid, reload, default_value)
    90         else:
    91         else:
    91             self._handle_relations(entity, rschema, role, divid, reload, default_value, formid)
    92             if self._is_composite():
    92 
    93                 self._handle_composite(entity, rschema, role, divid, reload, default_value, formid)
    93     def _handle_attributes(self, entity, rschema, role, divid, reload, default_value):
    94             else:
       
    95                 self._handle_relation(entity, rschema, role, divid, reload, default_value, formid)
       
    96 
       
    97     def _handle_attribute(self, entity, rschema, role, divid, reload, default_value):
    94         rtype = rschema.type
    98         rtype = rschema.type
    95         value = entity.printable_value(rtype)
    99         value = entity.printable_value(rtype)
    96         form, renderer = self._build_form(entity, rtype, role, divid, 'base',
   100         if not self._should_edit_attribute(entity, rschema):
    97                                           default_value, reload)
       
    98         if not self._should_edit_attribute(entity, rschema, form):
       
    99             self.w(value)
   101             self.w(value)
   100             return
   102             return
       
   103 
       
   104         display_label, related_entity = self._prepare_form(entity, rtype, role)
       
   105         form, renderer = self._build_form(entity, rtype, role, divid, 'base', default_value,
       
   106                                           reload, display_label, related_entity)
   101         value = value or default_value
   107         value = value or default_value
   102         field = form.field_by_name(rtype, role, entity.e_schema)
       
   103         form.append_field(field)
       
   104         self.view_form(divid, value, form, renderer)
   108         self.view_form(divid, value, form, renderer)
   105 
   109 
   106     def _handle_relations(self, entity, rschema, role, divid, reload, default_value, formid):
   110     def _compute_formid_value(self, entity, rschema, role, default_value, rvid, formid):
   107         rtype = rschema.type
   111         related_rset = entity.related(rschema.type, role)
   108         rvid = self._compute_best_vid(entity.e_schema, rschema, role)
       
   109         related_rset = entity.related(rtype, role)
       
   110         if related_rset:
   112         if related_rset:
   111             value = self._cw.view(rvid, related_rset)
   113             value = self._cw.view(rvid, related_rset)
   112         else:
   114         else:
   113             value = default_value
   115             value = default_value
       
   116         if not self._should_edit_relation(entity, rschema, role):
       
   117             return None, value
       
   118         return formid, value
       
   119 
       
   120     def _handle_relation(self, entity, rschema, role, divid, reload, default_value, formid):
       
   121         rvid = self._compute_best_vid(entity.e_schema, rschema, role)
       
   122         formid, value = self._compute_formid_value(entity, rschema, role, default_value, rvid, formid)
       
   123         if formid is None:
       
   124             return self.w(value)
       
   125 
       
   126         rtype = rschema.type
       
   127         display_label, related_entity = self._prepare_form(entity, rtype, role)
       
   128         form, renderer = self._build_form(entity, rtype, role, divid, formid, default_value, reload,
       
   129                                           display_label, related_entity, dict(vid=rvid))
       
   130         self.view_form(divid, value, form, renderer)
       
   131 
       
   132     def _handle_composite(self, entity, rschema, role, divid, reload, default_value, formid):
       
   133         # this is for attribute-like composites (1 target type, 1 related entity at most, for now)
   114         ttypes = self._compute_ttypes(rschema, role)
   134         ttypes = self._compute_ttypes(rschema, role)
   115 
   135         related_rset = entity.related(rschema.type, role)
   116         if not self._should_edit_relation(entity, rschema, role):
       
   117             self.w(value)
       
   118             return
       
   119         # this is for attribute-like composites (1 target type, 1 related entity at most)
       
   120         add_related = self._may_add_related(related_rset, entity, rschema, role, ttypes)
   136         add_related = self._may_add_related(related_rset, entity, rschema, role, ttypes)
   121         edit_related = self._may_edit_related_entity(related_rset, entity, rschema, role, ttypes)
   137         edit_related = self._may_edit_related_entity(related_rset, entity, rschema, role, ttypes)
   122         delete_related = edit_related and self._may_delete_related(related_rset, entity, rschema, role)
   138         delete_related = edit_related and self._may_delete_related(related_rset, entity, rschema, role)
   123         # compute formid
   139 
   124         if len(ttypes) > 1: # redundant safety belt
   140         rvid = self._compute_best_vid(entity.e_schema, rschema, role)
   125             formid = 'base'
   141         formid, value = self._compute_formid_value(entity, rschema, role, default_value, rvid, formid)
   126         else:
   142         if formid is None or not (edit_related or add_related):
   127             afs = uicfg.autoform_section.etype_get(entity.e_schema, rschema, role, ttypes[0])
   143             # till we learn to handle cases where not (edit_related or add_related)
   128             # is there an afs spec that says we should edit
   144             self.w(value)
   129             # the rschema as an attribute ?
   145             return
   130             if afs and 'main_attributes' in afs:
   146 
   131                 formid = 'base'
   147         rtype = rschema.type
   132 
   148         ttype = ttypes[0]
   133         form, renderer = self._build_form(entity, rtype, role, divid, formid, default_value,
   149         _fdata = self._prepare_composite_form(entity, rtype, role, edit_related, add_related and ttype)
   134                                           reload, dict(vid=rvid),
   150         display_label, related_entity = _fdata
   135                                           edit_related, add_related and ttypes[0])
   151         form, renderer = self._build_form(entity, rtype, role, divid, formid, default_value, reload,
   136         if formid == 'base':
   152                                           display_label, related_entity, dict(vid=rvid))
   137             field = form.field_by_name(rtype, role, entity.e_schema)
   153         self.view_form(divid, value, form, renderer,
   138             form.append_field(field)
   154                        edit_related, add_related, delete_related)
   139         self.view_form(divid, value, form, renderer, edit_related,
       
   140                        delete_related, add_related)
       
   141 
       
   142 
   155 
   143     def _compute_best_vid(self, eschema, rschema, role):
   156     def _compute_best_vid(self, eschema, rschema, role):
       
   157         rvid = self._one_rvid
   144         if eschema.rdef(rschema, role).role_cardinality(role) in '+*':
   158         if eschema.rdef(rschema, role).role_cardinality(role) in '+*':
   145             return self._many_rvid
   159             rvid = self._many_rvid
   146         return self._one_rvid
   160         return self._rules.get('rvid', rvid)
   147 
   161 
   148     def _compute_ttypes(self, rschema, role):
   162     def _compute_ttypes(self, rschema, role):
   149         dual_role = neg_role(role)
   163         dual_role = neg_role(role)
   150         return getattr(rschema, '%ss' % dual_role)()
   164         return getattr(rschema, '%ss' % dual_role)()
   151 
   165 
   152     def _compute_reload(self, entity, rschema, role, reload):
   166     def _compute_reload(self, entity, rschema, role, reload):
   153         rule = uicfg.reledit_ctrl.etype_get(entity.e_schema.type, rschema.type, role, '*')
   167         ctrl_reload = self._rules.get('reload', reload)
   154         ctrl_reload = rule.get('reload', reload)
       
   155         if callable(ctrl_reload):
   168         if callable(ctrl_reload):
   156             ctrl_reload = ctrl_reload(entity)
   169             ctrl_reload = ctrl_reload(entity)
   157         if isinstance(ctrl_reload, int) and ctrl_reload > 1: # not True/False
   170         if isinstance(ctrl_reload, int) and ctrl_reload > 1: # not True/False
   158             ctrl_reload = self._cw.build_url(ctrl_reload)
   171             ctrl_reload = self._cw.build_url(ctrl_reload)
   159         return ctrl_reload
   172         return ctrl_reload
   160 
   173 
   161     def _compute_default_value(self, entity, rschema, role, default_value):
   174     def _compute_default_value(self, entity, rschema, role, default_value):
   162         etype = entity.e_schema.type
   175         etype = entity.e_schema.type
   163         rule = uicfg.reledit_ctrl.etype_get(etype, rschema.type, role, '*')
   176         ctrl_default = self._rules.get('default_value', default_value)
   164         ctrl_default = rule.get('default_value', default_value)
       
   165         if ctrl_default:
   177         if ctrl_default:
   166             return ctrl_default
   178             return ctrl_default
   167         if default_value is None:
   179         if default_value is None:
   168             return xml_escape(self._cw._('<%s not specified>') %
   180             return xml_escape(self._cw._('<%s not specified>') %
   169                               display_name(self._cw, rschema.type, role))
   181                               display_name(self._cw, rschema.type, role))
   170         return default_value
   182         return default_value
   171 
   183 
   172     def _is_composite(self, eschema, rschema, role):
   184     def _is_composite(self):
   173         return eschema.rdef(rschema, role).composite == role
   185         return self._rules.get('edit_target') == 'related'
   174 
   186 
   175     def _may_add_related(self, related_rset, entity, rschema, role, ttypes):
   187     def _may_add_related(self, related_rset, entity, rschema, role, ttypes):
   176         """ ok for attribute-like composite entities """
   188         """ ok for attribute-like composite entities """
   177         if self._is_composite(entity.e_schema, rschema, role):
   189         if len(ttypes) > 1: # many etypes: learn how to do it
   178             if len(ttypes) > 1: # wrong cardinality: do not handle
   190             return False
   179                 return False
   191         rdef = rschema.role_rdef(entity.e_schema, ttypes[0], role)
   180             rdef = rschema.role_rdef(entity.e_schema, ttypes[0], role)
   192         card = rdef.role_cardinality(role)
   181             card = rdef.role_cardinality(role)
   193         if related_rset or card not in '?1':
   182             if related_rset and card in '?1':
   194             return False
   183                 return False
   195         if role == 'subject':
   184             if role == 'subject':
   196             kwargs = {'fromeid': entity.eid}
   185                 kwargs = {'fromeid': entity.eid}
   197         else:
   186             else:
   198             kwargs = {'toeid': entity.eid}
   187                 kwargs = {'toeid': entity.eid}
   199         return rdef.has_perm(self._cw, 'add', **kwargs)
   188             if rdef.has_perm(self._cw, 'add', **kwargs):
       
   189                 return True
       
   190         return False
       
   191 
   200 
   192     def _may_edit_related_entity(self, related_rset, entity, rschema, role, ttypes):
   201     def _may_edit_related_entity(self, related_rset, entity, rschema, role, ttypes):
   193         """ controls the edition of the related entity """
   202         """ controls the edition of the related entity """
       
   203         if len(ttypes) > 1 or len(related_rset.rows) != 1:
       
   204             return False
   194         if entity.e_schema.rdef(rschema, role).role_cardinality(role) not in '?1':
   205         if entity.e_schema.rdef(rschema, role).role_cardinality(role) not in '?1':
   195             return False
   206             return False
   196         if len(related_rset.rows) != 1:
       
   197             return False
       
   198         if len(ttypes) > 1:
       
   199             return False
       
   200         if not self._is_composite(entity.e_schema, rschema, role):
       
   201             return False
       
   202         return related_rset.get_entity(0, 0).cw_has_perm('update')
   207         return related_rset.get_entity(0, 0).cw_has_perm('update')
   203 
   208 
   204     def _may_delete_related(self, related_rset, entity, rschema, role):
   209     def _may_delete_related(self, related_rset, entity, rschema, role):
   205         # we assume may_edit_related
   210         # we assume may_edit_related, only 1 related entity
   206         kwargs = {'fromeid': entity.eid} if role == 'subject' else {'toeid': entity.eid}
   211         if not related_rset:
   207         if not rschema.has_perm(self._cw, 'delete', **kwargs):
   212             return False
   208             return False
   213         rentity = related_rset.get_entity(0, 0)
   209         for related_entity in related_rset.entities():
   214         if role == 'subject':
   210             if not related_entity.cw_has_perm('delete'):
   215             kwargs = {'fromeid': entity.eid, 'toeid': rentity.eid}
   211                 return False
   216         else:
   212         return True
   217             kwargs = {'fromeid': rentity.eid, 'toeid': entity.eid}
       
   218         # NOTE: should be sufficient given a well built schema/security
       
   219         return rschema.has_perm(self._cw, 'delete', **kwargs)
   213 
   220 
   214     def _build_edit_zone(self):
   221     def _build_edit_zone(self):
   215         return self._editzone % {'msg' : xml_escape(_(self._cw._(self._editzonemsg)))}
   222         return self._editzone % {'msg' : xml_escape(_(self._cw._(self._editzonemsg)))}
   216 
   223 
   217     def _build_delete_zone(self):
   224     def _build_delete_zone(self):
   232                       'role' : role, 'vid' : u''}
   239                       'role' : role, 'vid' : u''}
   233         if extradata:
   240         if extradata:
   234             event_args.update(extradata)
   241             event_args.update(extradata)
   235         return event_args
   242         return event_args
   236 
   243 
   237     def _build_form(self, entity, rtype, role, divid, formid, default_value, reload,
   244     def _prepare_form(self, entity, _rtype, role):
   238                     extradata=None, edit_related=False, add_related=False, **formargs):
   245         display_label = False
   239         event_args = self._build_args(entity, rtype, role, formid, default_value,
   246         related_entity = entity
   240                                       reload, extradata)
   247         return display_label, related_entity
   241         cancelclick = self._cancelclick % divid
   248 
       
   249     def _prepare_composite_form(self, entity, rtype, role, edit_related, add_related):
   242         if edit_related and not add_related:
   250         if edit_related and not add_related:
   243             display_fields = None
       
   244             display_label = True
   251             display_label = True
   245             related_entity = entity.related(rtype, role).get_entity(0, 0)
   252             related_entity = entity.related(rtype, role).get_entity(0, 0)
   246             self._cw.form['eid'] = related_entity.eid
       
   247         elif add_related:
   253         elif add_related:
   248             display_fields = None
       
   249             display_label = True
   254             display_label = True
   250             _new_entity = self._cw.vreg['etypes'].etype_class(add_related)(self._cw)
   255             _new_entity = self._cw.vreg['etypes'].etype_class(add_related)(self._cw)
   251             _new_entity.eid = self._cw.varmaker.next()
   256             _new_entity.eid = self._cw.varmaker.next()
   252             related_entity = _new_entity
   257             related_entity = _new_entity
       
   258             # XXX see forms.py ~ 276 and entities.linked_to method
       
   259             #     is there another way ?
   253             self._cw.form['__linkto'] = '%s:%s:%s' % (rtype, entity.eid, neg_role(role))
   260             self._cw.form['__linkto'] = '%s:%s:%s' % (rtype, entity.eid, neg_role(role))
   254         else: # base case: edition/attribute relation
   261         return display_label, related_entity
   255             display_fields = [(rtype, role)]
   262 
   256             display_label = False
   263     def _build_renderer(self, related_entity, display_label):
   257             related_entity = entity
   264         return self._cw.vreg['formrenderers'].select(
       
   265             self._form_renderer_id, self._cw, entity=related_entity,
       
   266             display_label=display_label,
       
   267             table_class='attributeForm' if display_label else '',
       
   268             display_help=False, button_bar_class='buttonbar',
       
   269             display_progress_div=False)
       
   270 
       
   271     def _build_form(self, entity, rtype, role, divid, formid, default_value, reload,
       
   272                     display_label, related_entity, extradata=None, **formargs):
       
   273         event_args = self._build_args(entity, rtype, role, formid, default_value,
       
   274                                       reload, extradata)
       
   275         cancelclick = self._cancelclick % divid
   258         form = self._cw.vreg['forms'].select(
   276         form = self._cw.vreg['forms'].select(
   259             formid, self._cw, rset=related_entity.as_rset(), entity=related_entity, domid='%s-form' % divid,
   277             formid, self._cw, rset=related_entity.as_rset(), entity=related_entity,
   260             display_fields=display_fields, formtype='inlined',
   278             domid='%s-form' % divid, formtype='inlined',
   261             action=self._cw.build_url('validateform?__onsuccess=window.parent.cw.reledit.onSuccess'),
   279             action=self._cw.build_url('validateform', __onsuccess='window.parent.cw.reledit.onSuccess'),
   262             cwtarget='eformframe', cssstyle='display: none',
   280             cwtarget='eformframe', cssclass='releditForm',
   263             **formargs)
   281             **formargs)
   264         # pass reledit arguments
   282         # pass reledit arguments
   265         for pname, pvalue in event_args.iteritems():
   283         for pname, pvalue in event_args.iteritems():
   266             form.add_hidden('__reledit|' + pname, pvalue)
   284             form.add_hidden('__reledit|' + pname, pvalue)
   267         # handle buttons
   285         # handle buttons
   277             form.form_buttons = form_buttons
   295             form.form_buttons = form_buttons
   278         else: # base
   296         else: # base
   279             form.form_buttons = [SubmitButton(),
   297             form.form_buttons = [SubmitButton(),
   280                                  Button(stdmsgs.BUTTON_CANCEL, onclick=cancelclick)]
   298                                  Button(stdmsgs.BUTTON_CANCEL, onclick=cancelclick)]
   281         form.event_args = event_args
   299         form.event_args = event_args
   282         renderer = self._cw.vreg['formrenderers'].select(
   300         if formid == 'base':
   283             'base', self._cw, entity=related_entity, display_label=display_label,
   301             field = form.field_by_name(rtype, role, entity.e_schema)
   284             display_help=False, table_class='',
   302             form.append_field(field)
   285             button_bar_class='buttonbar', display_progress_div=False)
   303         return form, self._build_renderer(related_entity, display_label)
   286         return form, renderer
   304 
   287 
   305     def _should_edit_attribute(self, entity, rschema):
   288     def _should_edit_attribute(self, entity, rschema, form):
       
   289         # examine rtags
       
   290         noedit = uicfg.reledit_ctrl.etype_get(entity.e_schema, rschema.type, 'subject').get('noedit', False)
       
   291         if noedit:
       
   292             return False
       
   293         rdef = entity.e_schema.rdef(rschema)
   306         rdef = entity.e_schema.rdef(rschema)
   294         afs = uicfg.autoform_section.etype_get(entity.__regid__, rschema, 'subject', rdef.object)
       
   295         if 'main_hidden' in  afs:
       
   296             return False
       
   297         # check permissions
   307         # check permissions
   298         if not entity.cw_has_perm('update'):
   308         if not entity.cw_has_perm('update'):
   299             return False
   309             return False
   300         rdef = entity.e_schema.rdef(rschema)
   310         rdef = entity.e_schema.rdef(rschema)
   301         if not rdef.has_perm(self._cw, 'update', eid=entity.eid):
   311         return rdef.has_perm(self._cw, 'update', eid=entity.eid)
   302             return False
   312 
   303         # XXX ?
   313     should_edit_attributes = deprecated('[3.9] should_edit_attributes is deprecated,'
   304         try:
   314                                         ' use _should_edit_attribute instead',
   305             form.field_by_name(str(rschema), 'subject', entity.e_schema)
   315                                         _should_edit_attribute)
   306         except FieldNotFound:
       
   307             return False
       
   308         return True
       
   309 
   316 
   310     def _should_edit_relation(self, entity, rschema, role):
   317     def _should_edit_relation(self, entity, rschema, role):
   311         # examine rtags
   318         # examine rtags
   312         rtype = rschema.type
   319         rtype = rschema.type
   313         noedit = uicfg.reledit_ctrl.etype_get(entity.e_schema, rtype, role).get('noedit', False)
       
   314         if noedit:
       
   315             return False
       
   316         rdef = entity.e_schema.rdef(rschema, role)
   320         rdef = entity.e_schema.rdef(rschema, role)
   317         afs = uicfg.autoform_section.etype_get(
       
   318             entity.__regid__, rschema, role, rdef.object)
       
   319         if 'main_hidden' in afs:
       
   320             return False
       
   321         perm_args = {'fromeid': entity.eid} if role == 'subject' else {'toeid': entity.eid}
   321         perm_args = {'fromeid': entity.eid} if role == 'subject' else {'toeid': entity.eid}
   322         return rschema.has_perm(self._cw, 'add', **perm_args)
   322         return rschema.has_perm(self._cw, 'add', **perm_args)
   323 
   323 
   324     def view_form(self, divid, value, form=None, renderer=None,
   324     should_edit_relations = deprecated('[3.9] should_edit_relations is deprecated,'
   325                   edit_related=False, delete_related=False, add_related=False):
   325                                        ' use _should_edit_relation instead',
       
   326                                        _should_edit_relation)
       
   327 
       
   328     def _open_form_wrapper(self, divid, value, form, renderer):
   326         w = self.w
   329         w = self.w
   327         w(u'<div id="%(id)s-reledit" onmouseout="%(out)s" onmouseover="%(over)s">' %
   330         w(u'<div id="%(id)s-reledit" onmouseout="%(out)s" onmouseover="%(over)s" class="%(css)s">' %
   328           {'id': divid,
   331           {'id': divid, 'css': 'releditField',
   329            'out': "jQuery('#%s').addClass('hidden')" % divid,
   332            'out': "jQuery('#%s').addClass('hidden')" % divid,
   330            'over': "jQuery('#%s').removeClass('hidden')" % divid})
   333            'over': "jQuery('#%s').removeClass('hidden')" % divid})
   331         w(u'<div id="%s-value" class="editableFieldValue">' % divid)
   334         w(u'<div id="%s-value" class="editableFieldValue">' % divid)
   332         w(value)
   335         w(value)
   333         w(u'</div>')
   336         w(u'</div>')
   334         w(form.render(renderer=renderer))
   337         w(form.render(renderer=renderer))
   335         w(u'<div id="%s" class="editableField hidden">' % divid)
   338         w(u'<div id="%s" class="editableField hidden">' % divid)
       
   339 
       
   340     def _close_form_wrapper(self):
       
   341         self.w(u'</div>')
       
   342         self.w(u'</div>')
       
   343 
       
   344     def view_form(self, divid, value, form=None, renderer=None,
       
   345                   edit_related=False, add_related=False, delete_related=False):
       
   346         self._open_form_wrapper(divid, value, form, renderer)
       
   347         w = self.w
   336         args = form.event_args.copy()
   348         args = form.event_args.copy()
   337         if not add_related: # excludes edition
   349         if not add_related: # currently, excludes edition
   338             args['formid'] = 'edition'
   350             args['formid'] = 'edition' if edit_related else 'base'
   339             w(u'<div id="%s-update" class="editableField" onclick="%s" title="%s">' %
   351             w(u'<div id="%s-update" class="editableField" onclick="%s" title="%s">' %
   340               (divid, xml_escape(self._onclick % args), self._cw._(self._editzonemsg)))
   352               (divid, xml_escape(self._onclick % args), self._cw._(self._editzonemsg)))
   341             w(self._build_edit_zone())
   353             w(self._build_edit_zone())
   342             w(u'</div>')
   354             w(u'</div>')
   343         else:
   355         else:
   344             args['formid'] = 'edition'
   356             args['formid'] = 'edition' if add_related else 'base'
   345             w(u'<div id="%s-add" class="editableField" onclick="%s" title="%s">' %
   357             w(u'<div id="%s-add" class="editableField" onclick="%s" title="%s">' %
   346               (divid, xml_escape(self._onclick % args), self._cw._(self._addmsg)))
   358               (divid, xml_escape(self._onclick % args), self._cw._(self._addmsg)))
   347             w(self._build_add_zone())
   359             w(self._build_add_zone())
   348             w(u'</div>')
   360             w(u'</div>')
   349         if delete_related:
   361         if delete_related:
   350             args['formid'] = 'deleteconf'
   362             args['formid'] = 'deleteconf'
   351             w(u'<div id="%s-delete" class="editableField" onclick="%s" title="%s">' %
   363             w(u'<div id="%s-delete" class="editableField" onclick="%s" title="%s">' %
   352               (divid, xml_escape(self._onclick % args), self._cw._(self._deletemsg)))
   364               (divid, xml_escape(self._onclick % args), self._cw._(self._deletemsg)))
   353             w(self._build_delete_zone())
   365             w(self._build_delete_zone())
   354             w(u'</div>')
   366             w(u'</div>')
   355         w(u'</div>')
   367         self._close_form_wrapper()
   356         w(u'</div>')
   368 
   357 
   369 
   358 class AutoClickAndEditFormView(ClickAndEditFormView):
   370 class AutoClickAndEditFormView(ClickAndEditFormView):
   359     __regid__ = 'reledit'
   371     __regid__ = 'reledit'
   360 
   372 
   361     def _build_form(self, entity, rtype, role, divid, formid, default_value, reload,
   373     def _build_form(self, entity, rtype, role, divid, formid, default_value, reload,
   362                   extradata=None, edit_related=False, add_related=False, **formargs):
   374                     display_label, related_entity, extradata=None, **formargs):
   363         event_args = self._build_args(entity, rtype, role, 'base', default_value,
   375         event_args = self._build_args(entity, rtype, role, 'base', default_value,
   364                                       reload, extradata)
   376                                       reload, extradata)
   365         form = _DummyForm()
   377         form = _DummyForm()
   366         form.event_args = event_args
   378         form.event_args = event_args
   367         return form, None
   379         return form, None