web/views/autoform.py
changeset 4277 35cd057339b2
parent 4252 6c4f109c2b03
child 4295 b9590e68c543
equal deleted inserted replaced
4276:e2ed81c20e74 4277:35cd057339b2
     7 """
     7 """
     8 
     8 
     9 __docformat__ = "restructuredtext en"
     9 __docformat__ = "restructuredtext en"
    10 _ = unicode
    10 _ = unicode
    11 
    11 
    12 from logilab.common.decorators import cached
    12 from logilab.common.decorators import cached, iclassmethod
    13 
    13 
    14 from cubicweb import typed_eid
    14 from cubicweb import typed_eid
    15 from cubicweb.web import stdmsgs, uicfg
    15 from cubicweb.web import stdmsgs, uicfg
    16 from cubicweb.web import form, formwidgets as fwdgs
    16 from cubicweb.web import form, formwidgets as fwdgs
    17 from cubicweb.web.views import forms, editforms
    17 from cubicweb.web.views import forms, editforms, editviews
    18 
    18 
    19 _afs = uicfg.autoform_section
    19 _afs = uicfg.autoform_section
    20 
    20 
    21 class AutomaticEntityForm(forms.EntityFieldsForm):
    21 class AutomaticEntityForm(forms.EntityFieldsForm):
    22     """base automatic form to edit any entity.
    22     """base automatic form to edit any entity.
    41     # for attributes selection when searching in uicfg.autoform_section
    41     # for attributes selection when searching in uicfg.autoform_section
    42     formtype = 'main'
    42     formtype = 'main'
    43     # set this to a list of [(relation, role)] if you want to explictily tell
    43     # set this to a list of [(relation, role)] if you want to explictily tell
    44     # which relations should be edited
    44     # which relations should be edited
    45     display_fields = None
    45     display_fields = None
       
    46 
       
    47     def _generic_relations_field(self):
       
    48         try:
       
    49             srels_by_cat = self.srelations_by_category('generic', 'add', strict=True)
       
    50             warn('[3.6] %s: srelations_by_category is deprecated, use uicfg or '
       
    51                  'override editable_relations instead' % classid(form),
       
    52                  DeprecationWarning)
       
    53         except AttributeError:
       
    54             srels_by_cat = self.editable_relations()
       
    55         if not srels_by_cat:
       
    56             raise form.FieldNotFound('_cw_generic_field')
       
    57         return editviews.GenericRelationsField(self.editable_relations())
       
    58 
       
    59     @iclassmethod
       
    60     def field_by_name(cls_or_self, name, role=None, eschema=None):
       
    61         """return field with the given name and role. If field is not explicitly
       
    62         defined for the form but `eclass` is specified, guess_field will be
       
    63         called.
       
    64         """
       
    65         try:
       
    66             return super(AutomaticEntityForm, cls_or_self).field_by_name(name, role, eschema)
       
    67         except form.FieldNotFound:
       
    68             if name == '_cw_generic_field' and not isinstance(cls_or_self, type):
       
    69                 return cls_or_self._generic_relations_field()
       
    70             raise
    46 
    71 
    47     # base automatic entity form methods #######################################
    72     # base automatic entity form methods #######################################
    48 
    73 
    49     def __init__(self, *args, **kwargs):
    74     def __init__(self, *args, **kwargs):
    50         super(AutomaticEntityForm, self).__init__(*args, **kwargs)
    75         super(AutomaticEntityForm, self).__init__(*args, **kwargs)
    62                                                eschema=entity.e_schema)
    87                                                eschema=entity.e_schema)
    63                     self.fields.append(field)
    88                     self.fields.append(field)
    64                 except form.FieldNotFound:
    89                 except form.FieldNotFound:
    65                     # meta attribute such as <attr>_format
    90                     # meta attribute such as <attr>_format
    66                     continue
    91                     continue
       
    92         if self.formtype == 'main' and entity.has_eid():
       
    93             try:
       
    94                 self.fields.append(self.field_by_name('_cw_generic_field'))
       
    95             except form.FieldNotFound:
       
    96                 # no editable relation
       
    97                 pass
    67         self.maxrelitems = self._cw.property_value('navigation.related-limit')
    98         self.maxrelitems = self._cw.property_value('navigation.related-limit')
    68         self.force_display = bool(self._cw.form.get('__force_display'))
    99         self.force_display = bool(self._cw.form.get('__force_display'))
    69         fnum = len(self.fields)
   100         fnum = len(self.fields)
    70         self.fields.sort(key=lambda f: f.order is None and fnum or f.order)
   101         self.fields.sort(key=lambda f: f.order is None and fnum or f.order)
    71 
   102 
   160         given category(ies) and permission
   191         given category(ies) and permission
   161         """
   192         """
   162         return self._relations_by_section('inlined')
   193         return self._relations_by_section('inlined')
   163 
   194 
   164     # generic relations modifier ###############################################
   195     # generic relations modifier ###############################################
   165 
       
   166     def relations_table(self):
       
   167         """yiels 3-tuples (rtype, target, related_list)
       
   168         where <related_list> itself a list of :
       
   169           - node_id (will be the entity element's DOM id)
       
   170           - appropriate javascript's togglePendingDelete() function call
       
   171           - status 'pendingdelete' or ''
       
   172           - oneline view of related entity
       
   173         """
       
   174         entity = self.edited_entity
       
   175         pending_deletes = self._cw.get_pending_deletes(entity.eid)
       
   176         for label, rschema, role in self.editable_relations():
       
   177             relatedrset = entity.related(rschema, role, limit=self.related_limit)
       
   178             if rschema.has_perm(self._cw, 'delete'):
       
   179                 toggleable_rel_link_func = editforms.toggleable_relation_link
       
   180             else:
       
   181                 toggleable_rel_link_func = lambda x, y, z: u''
       
   182             related = []
       
   183             for row in xrange(relatedrset.rowcount):
       
   184                 nodeid = editforms.relation_id(entity.eid, rschema, role,
       
   185                                                relatedrset[row][0])
       
   186                 if nodeid in pending_deletes:
       
   187                     status = u'pendingDelete'
       
   188                     label = '+'
       
   189                 else:
       
   190                     status = u''
       
   191                     label = 'x'
       
   192                 dellink = toggleable_rel_link_func(entity.eid, nodeid, label)
       
   193                 eview = self._cw.view('oneline', relatedrset, row=row)
       
   194                 related.append((nodeid, dellink, status, eview))
       
   195             yield (rschema, role, related)
       
   196 
       
   197     def restore_pending_inserts(self, cell=False):
       
   198         """used to restore edition page as it was before clicking on
       
   199         'search for <some entity type>'
       
   200         """
       
   201         eid = self.edited_entity.eid
       
   202         cell = cell and "div_insert_" or "tr"
       
   203         pending_inserts = set(self._cw.get_pending_inserts(eid))
       
   204         for pendingid in pending_inserts:
       
   205             eidfrom, rtype, eidto = pendingid.split(':')
       
   206             if typed_eid(eidfrom) == eid: # subject
       
   207                 label = display_name(self._cw, rtype, 'subject',
       
   208                                      self.edited_entity.__regid__)
       
   209                 reid = eidto
       
   210             else:
       
   211                 label = display_name(self._cw, rtype, 'object',
       
   212                                      self.edited_entity.__regid__)
       
   213                 reid = eidfrom
       
   214             jscall = "javascript: cancelPendingInsert('%s', '%s', null, %s);" \
       
   215                      % (pendingid, cell, eid)
       
   216             rset = self._cw.eid_rset(reid)
       
   217             eview = self._cw.view('text', rset, row=0)
       
   218             # XXX find a clean way to handle baskets
       
   219             if rset.description[0][0] == 'Basket':
       
   220                 eview = '%s (%s)' % (eview, display_name(self._cw, 'Basket'))
       
   221             yield rtype, pendingid, jscall, label, reid, eview
       
   222 
   196 
   223     # inlined forms support ####################################################
   197     # inlined forms support ####################################################
   224 
   198 
   225     @cached
   199     @cached
   226     def inlined_form_views(self):
   200     def inlined_form_views(self):