web/views/autoform.py
branchstable
changeset 3518 11ce4682187d
parent 3470 c9c8b231db7b
child 3521 ad041dae15aa
equal deleted inserted replaced
3517:8832e231fad7 3518:11ce4682187d
     6 :license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
     6 :license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
     7 """
     7 """
     8 __docformat__ = "restructuredtext en"
     8 __docformat__ = "restructuredtext en"
     9 _ = unicode
     9 _ = unicode
    10 
    10 
    11 from logilab.common.decorators import iclassmethod
    11 from logilab.common.decorators import iclassmethod, cached
    12 
    12 
    13 from cubicweb import typed_eid
    13 from cubicweb import typed_eid
    14 from cubicweb.web import stdmsgs, uicfg
    14 from cubicweb.web import stdmsgs, uicfg
    15 from cubicweb.web import form, formwidgets as fwdgs
    15 from cubicweb.web import form, formwidgets as fwdgs
    16 from cubicweb.web.formfields import guess_field
    16 from cubicweb.web.formfields import guess_field
   192     @property
   192     @property
   193     def form_needs_multipart(self):
   193     def form_needs_multipart(self):
   194         """true if the form needs enctype=multipart/form-data"""
   194         """true if the form needs enctype=multipart/form-data"""
   195         return self._subform_needs_multipart()
   195         return self._subform_needs_multipart()
   196 
   196 
       
   197     def build_context(self, rendervalues=None):
       
   198         super(AutomaticEntityForm, self).build_context(rendervalues)
       
   199         for form in self.inlined_forms():
       
   200             form.build_context(rendervalues)
       
   201 
   197     def _subform_needs_multipart(self, _tested=None):
   202     def _subform_needs_multipart(self, _tested=None):
   198         if _tested is None:
   203         if _tested is None:
   199             _tested = set()
   204             _tested = set()
   200         if super(AutomaticEntityForm, self).form_needs_multipart:
   205         if super(AutomaticEntityForm, self).form_needs_multipart:
   201             return True
   206             return True
   335                 eview = '%s (%s)' % (eview, display_name(self.req, 'Basket'))
   340                 eview = '%s (%s)' % (eview, display_name(self.req, 'Basket'))
   336             yield rtype, pendingid, jscall, label, reid, eview
   341             yield rtype, pendingid, jscall, label, reid, eview
   337 
   342 
   338     # inlined forms support ####################################################
   343     # inlined forms support ####################################################
   339 
   344 
       
   345     @cached
       
   346     def inlined_form_views(self):
       
   347         """compute and return list of inlined form views (hosting the inlined form object)
       
   348         """
       
   349         formviews = []
       
   350         entity = self.edited_entity
       
   351         for rschema, ttypes, role in self.inlined_relations():
       
   352             # show inline forms only if there's one possible target type
       
   353             # for rschema
       
   354             if len(ttypes) != 1:
       
   355                 self.warning('entity related by the %s relation should have '
       
   356                              'inlined form but there is multiple target types, '
       
   357                              'dunno what to do', rschema)
       
   358                 continue
       
   359             ttype = ttypes[0].type
       
   360             if self.should_inline_relation_form(rschema, ttype, role):
       
   361                 formviews += self.inline_edition_form_view(rschema, ttype, role)
       
   362                 if role == 'subject':
       
   363                     card = rschema.rproperty(entity.e_schema, ttype, 'cardinality')[0]
       
   364                 else:
       
   365                     card = rschema.rproperty(ttype, entity.e_schema, 'cardinality')[1]
       
   366                 # there is no related entity and we need at least one: we need to
       
   367                 # display one explicit inline-creation view
       
   368                 if self.should_display_inline_creation_form(rschema, formviews, card):
       
   369                     formviews += self.inline_creation_form_view(rschema, ttype, role)
       
   370                 # we can create more than one related entity, we thus display a link
       
   371                 # to add new related entities
       
   372                 if self.should_display_add_new_relation_link(rschema, formviews, card):
       
   373                     addnewlink = self.vreg['views'].select(
       
   374                         'inline-addnew-link', self.req,
       
   375                         etype=ttype, rtype=rschema, role=role,
       
   376                         peid=self.edited_entity.eid, pform=self, card=card)
       
   377                     formviews.append(addnewlink)
       
   378         return formviews
       
   379 
       
   380     def inlined_forms(self):
       
   381         for formview in self.inlined_form_views():
       
   382             if formview.form: # may be None for the addnew_link artefact form
       
   383                 yield formview.form
       
   384 
   340     def should_inline_relation_form(self, rschema, targettype, role):
   385     def should_inline_relation_form(self, rschema, targettype, role):
   341         """return true if the given relation with entity has role and a
   386         """return true if the given relation with entity has role and a
   342         targettype target should be inlined
   387         targettype target should be inlined
   343         """
   388         """
   344         return self.rinlined.etype_get(self.edited_entity.id, rschema, role,
   389         return self.rinlined.etype_get(self.edited_entity.id, rschema, role,
   345                                        targettype)
   390                                        targettype)
   346 
   391 
   347     def display_inline_edition_form(self, w, rschema, targettype, role,
   392     def should_display_inline_creation_form(self, rschema, existant, card):
   348                                      i18nctx):
   393         """return true if a creation form should be inlined
   349         """display inline forms for already related entities.
   394 
   350 
   395         by default true if there is no related entity and we need at least one
   351         Return True if some inlined form are actually displayed
   396         """
   352         """
   397         return not existant and card in '1+' or self.req.form.has_key('force_%s_display' % rschema)
   353         existant = False
   398 
       
   399     def should_display_add_new_relation_link(self, rschema, existant, card):
       
   400         """return true if we should add a link to add a new creation form
       
   401         (through ajax call)
       
   402 
       
   403         by default true if there is no related entity or if the relation has
       
   404         multiple cardinality
       
   405         """
       
   406         return not existant or card in '+*'
       
   407 
       
   408     def should_hide_add_new_relation_link(self, rschema, card):
       
   409         """return true if once an inlined creation form is added, the 'add new'
       
   410         link should be hidden
       
   411 
       
   412         by default true if the relation has single cardinality
       
   413         """
       
   414         return card in '1?'
       
   415 
       
   416     def inline_edition_form_view(self, rschema, ttype, role):
       
   417         """yield inline form views for already related entities through the
       
   418         given relation
       
   419         """
   354         entity = self.edited_entity
   420         entity = self.edited_entity
   355         related = entity.has_eid() and entity.related(rschema, role)
   421         related = entity.has_eid() and entity.related(rschema, role)
   356         if related:
   422         if related:
       
   423             vvreg = self.vreg['views']
   357             # display inline-edition view for all existing related entities
   424             # display inline-edition view for all existing related entities
   358             for i, relentity in enumerate(related.entities()):
   425             for i, relentity in enumerate(related.entities()):
   359                 if relentity.has_perm('update'):
   426                 if relentity.has_perm('update'):
   360                     w(self.view('inline-edition', related, row=i, col=0,
   427                     yield vvreg.select('inline-edition', self.req, related,
   361                                 rtype=rschema, role=role, ptype=entity.e_schema,
   428                                        row=i, col=0, rtype=rschema, role=role,
   362                                 peid=entity.eid, i18nctx=i18nctx))
   429                                        peid=entity.eid, pform=self)
   363                     existant = True
   430 
   364         return existant
   431     def inline_creation_form_view(self, rschema, ttype, role):
   365 
   432         """yield inline form views to a newly related (hence created) entity
   366     def should_display_inline_creation_form(self, rschema, existant, card):
   433         through the given relation
   367         """return true if a creation form should be inlined
   434         """
   368 
   435         yield self.vreg['views'].select('inline-creation', self.req,
   369         by default true if there is no related entity and we need at least one
   436                                         etype=ttype, rtype=rschema, role=role,
   370         """
   437                                         peid=self.edited_entity.eid, pform=self)
   371         return not existant and card in '1+' or self.req.form.has_key('force_%s_display' % rschema)
       
   372 
       
   373     def display_inline_creation_form(self, w, rschema, targettype, role,
       
   374                                      i18nctx):
       
   375         """display inline forms to a newly related (hence created) entity.
       
   376 
       
   377         Return True if some inlined form are actually displayed
       
   378         """
       
   379         entity = self.edited_entity
       
   380         w(self.view('inline-creation', None, etype=targettype,
       
   381                     peid=entity.eid, ptype=entity.e_schema,
       
   382                     rtype=rschema, role=role, i18nctx=i18nctx))
       
   383 
       
   384     def should_display_add_new_relation_link(self, rschema, existant, card):
       
   385         """return true if we should add a link to add a new creation form
       
   386         (through ajax call)
       
   387 
       
   388         by default true if there is no related entity or if the relation has
       
   389         multiple cardinality
       
   390         """
       
   391         return not existant or card in '+*'
       
   392 
       
   393     def should_hide_add_new_relation_link(self, rschema, card):
       
   394         """return true if once an inlined creation form is added, the 'add new'
       
   395         link should be hidden
       
   396 
       
   397         by default true if the relation has single cardinality
       
   398         """
       
   399         return card in '1?'
       
   400 
   438 
   401 
   439 
   402 def etype_relation_field(etype, rtype, role='subject'):
   440 def etype_relation_field(etype, rtype, role='subject'):
   403     eschema = AutomaticEntityForm.schema.eschema(etype)
   441     eschema = AutomaticEntityForm.schema.eschema(etype)
   404     return AutomaticEntityForm.field_by_name(rtype, role, eschema)
   442     return AutomaticEntityForm.field_by_name(rtype, role, eschema)