web/views/editforms.py
branchstable
changeset 3518 11ce4682187d
parent 3513 c002f6488631
child 3524 a3431f4e2f40
child 3532 df045bc51d00
equal deleted inserted replaced
3517:8832e231fad7 3518:11ce4682187d
    12 from copy import copy
    12 from copy import copy
    13 
    13 
    14 from simplejson import dumps
    14 from simplejson import dumps
    15 
    15 
    16 from logilab.mtconverter import xml_escape
    16 from logilab.mtconverter import xml_escape
       
    17 from logilab.common.decorators import cached
    17 
    18 
    18 from cubicweb.selectors import (match_kwargs, one_line_rset, non_final_entity,
    19 from cubicweb.selectors import (match_kwargs, one_line_rset, non_final_entity,
    19                                 specified_etype_implements, yes)
    20                                 specified_etype_implements, yes)
    20 from cubicweb.utils import make_uid
    21 from cubicweb.utils import make_uid
    21 from cubicweb.view import EntityView
    22 from cubicweb.view import EntityView
   437         form = self.vreg['forms'].select(self.id, self.req, rset=self.rset)
   438         form = self.vreg['forms'].select(self.id, self.req, rset=self.rset)
   438         self.w(form.form_render())
   439         self.w(form.form_render())
   439 
   440 
   440 
   441 
   441 class InlineEntityEditionFormView(FormViewMixIn, EntityView):
   442 class InlineEntityEditionFormView(FormViewMixIn, EntityView):
       
   443     """
       
   444     :attr peid: the parent entity's eid hosting the inline form
       
   445     :attr rtype: the relation bridging `etype` and `peid`
       
   446     :attr role: the role played by the `peid` in the relation
       
   447     :attr pform: the parent form where this inlined form is being displayed
       
   448     """
   442     id = 'inline-edition'
   449     id = 'inline-edition'
   443     __select__ = non_final_entity() & match_kwargs('peid', 'rtype')
   450     __select__ = non_final_entity() & match_kwargs('peid', 'rtype')
       
   451 
       
   452     _select_attrs = ('peid', 'rtype', 'role', 'pform')
   444     removejs = "removeInlinedEntity('%s', '%s', '%s')"
   453     removejs = "removeInlinedEntity('%s', '%s', '%s')"
   445 
   454 
   446     def call(self, **kwargs):
   455     def __init__(self, *args, **kwargs):
   447         """redefine default call() method to avoid automatic
   456         for attr in self._select_attrs:
   448         insertions of <div class="section"> between each row of
   457             setattr(self, attr, kwargs.pop(attr, None))
   449         the resultset
   458         super(InlineEntityEditionFormView, self).__init__(*args, **kwargs)
   450         """
   459 
   451         rset = self.rset
   460     def _entity(self):
   452         for i in xrange(len(rset)):
   461         assert self.row is not None, self
   453             self.wview(self.id, rset, row=i, **kwargs)
   462         return self.rset.get_entity(self.row, self.col)
   454 
   463 
   455     def cell_call(self, row, col, peid, rtype, role, i18nctx, **kwargs):
   464     @property
       
   465     @cached
       
   466     def form(self):
       
   467         entity = self._entity()
       
   468         form = self.vreg['forms'].select('edition', self.req,
       
   469                                          entity=entity,
       
   470                                          form_renderer_id='inline',
       
   471                                          mainform=False, copy_nav_params=False,
       
   472                                          **self.extra_kwargs)
       
   473         form.parent_form = self.pform
       
   474         self.add_hiddens(form, entity)
       
   475         return form
       
   476 
       
   477     def cell_call(self, row, col, i18nctx, **kwargs):
   456         """
   478         """
   457         :param peid: the parent entity's eid hosting the inline form
   479         :param peid: the parent entity's eid hosting the inline form
   458         :param rtype: the relation bridging `etype` and `peid`
   480         :param rtype: the relation bridging `etype` and `peid`
   459         :param role: the role played by the `peid` in the relation
   481         :param role: the role played by the `peid` in the relation
   460         """
   482         """
   461         entity = self.entity(row, col)
   483         entity = self._entity()
   462         divonclick = "restoreInlinedEntity('%s', '%s', '%s')" % (peid, rtype,
   484         divonclick = "restoreInlinedEntity('%s', '%s', '%s')" % (
   463                                                                  entity.eid)
   485             self.peid, self.rtype, entity.eid)
   464         self.render_form(entity, peid, rtype, role, i18nctx,
   486         self.render_form(i18nctx, divonclick=divonclick, **kwargs)
   465                          divonclick=divonclick)
   487 
   466 
   488     def render_form(self, i18nctx, **kwargs):
   467     def render_form(self, entity, peid, rtype, role, i18nctx, **kwargs):
       
   468         """fetch and render the form"""
   489         """fetch and render the form"""
   469         form = self.vreg['forms'].select('edition', self.req, entity=entity,
   490         entity = self._entity()
   470                                          form_renderer_id='inline',
   491         divid = '%s-%s-%s' % (self.peid, self.rtype, entity.eid)
   471                                          mainform=False, copy_nav_params=False)
       
   472         self.add_hiddens(form, entity, peid, rtype, role)
       
   473         divid = '%s-%s-%s' % (peid, rtype, entity.eid)
       
   474         title = self.req.pgettext(i18nctx, 'This %s' % entity.e_schema)
   492         title = self.req.pgettext(i18nctx, 'This %s' % entity.e_schema)
   475         removejs = self.removejs % (peid, rtype, entity.eid)
   493         removejs = self.removejs % (self.peid, self.rtype, entity.eid)
   476         countkey = '%s_count' % rtype
   494         countkey = '%s_count' % self.rtype
   477         try:
   495         try:
   478             self.req.data[countkey] += 1
   496             self.req.data[countkey] += 1
   479         except:
   497         except KeyError:
   480             self.req.data[countkey] = 1
   498             self.req.data[countkey] = 1
   481         self.w(form.form_render(divid=divid, title=title, removejs=removejs,
   499         self.w(self.form.form_render(
   482                                 i18nctx=i18nctx,
   500             divid=divid, title=title, removejs=removejs, i18nctx=i18nctx,
   483                                 counter=self.req.data[countkey], **kwargs))
   501             counter=self.req.data[countkey], **kwargs))
   484 
   502 
   485     def add_hiddens(self, form, entity, peid, rtype, role):
   503     def add_hiddens(self, form, entity):
   486         # to ease overriding (see cubes.vcsfile.views.forms for instance)
   504         # to ease overriding (see cubes.vcsfile.views.forms for instance)
   487         if self.keep_entity(form, entity, peid, rtype):
   505         if self.keep_entity(form, entity):
   488             if entity.has_eid():
   506             if entity.has_eid():
   489                 rval = entity.eid
   507                 rval = entity.eid
   490             else:
   508             else:
   491                 rval = INTERNAL_FIELD_VALUE
   509                 rval = INTERNAL_FIELD_VALUE
   492             form.form_add_hidden('edit%s-%s:%s' % (role[0], rtype, peid), rval)
   510             form.form_add_hidden('edit%s-%s:%s' % (self.role[0], self.rtype, self.peid), rval)
   493         form.form_add_hidden(name='%s:%s' % (rtype, peid), value=entity.eid,
   511         form.form_add_hidden(name='%s:%s' % (self.rtype, self.peid), value=entity.eid,
   494                              id='rel-%s-%s-%s'  % (peid, rtype, entity.eid))
   512                              id='rel-%s-%s-%s'  % (self.peid, self.rtype, entity.eid))
   495 
   513 
   496     def keep_entity(self, form, entity, peid, rtype):
   514     def keep_entity(self, form, entity):
   497         if not entity.has_eid():
   515         if not entity.has_eid():
   498             return True
   516             return True
   499         # are we regenerating form because of a validation error ?
   517         # are we regenerating form because of a validation error ?
   500         if form.form_previous_values:
   518         if form.form_previous_values:
   501             cdvalues = self.req.list_form_param(eid_param(rtype, peid),
   519             cdvalues = self.req.list_form_param(eid_param(self.rtype, self.peid),
   502                                                 form.form_previous_values)
   520                                                 form.form_previous_values)
   503             if unicode(entity.eid) not in cdvalues:
   521             if unicode(entity.eid) not in cdvalues:
   504                 return False
   522                 return False
   505         return True
   523         return True
   506 
   524 
   507 
   525 
   508 class InlineEntityCreationFormView(InlineEntityEditionFormView):
   526 class InlineEntityCreationFormView(InlineEntityEditionFormView):
       
   527     """
       
   528     :attr etype: the entity type being created in the inline form
       
   529     """
   509     id = 'inline-creation'
   530     id = 'inline-creation'
   510     __select__ = (match_kwargs('peid', 'rtype')
   531     __select__ = (match_kwargs('peid', 'rtype')
   511                   & specified_etype_implements('Any'))
   532                   & specified_etype_implements('Any'))
       
   533     _select_attrs = InlineEntityEditionFormView._select_attrs + ('etype',)
   512     removejs = "removeInlineForm('%s', '%s', '%s')"
   534     removejs = "removeInlineForm('%s', '%s', '%s')"
   513 
   535 
   514     def call(self, etype, peid, rtype, role, i18nctx, **kwargs):
   536     @cached
   515         """
   537     def _entity(self):
   516         :param etype: the entity type being created in the inline form
       
   517         :param peid: the parent entity's eid hosting the inline form
       
   518         :param rtype: the relation bridging `etype` and `peid`
       
   519         :param role: the role played by the `peid` in the relation
       
   520         """
       
   521         try:
   538         try:
   522             cls = self.vreg['etypes'].etype_class(etype)
   539             cls = self.vreg['etypes'].etype_class(self.etype)
   523         except:
   540         except:
   524             self.w(self.req._('no such entity type %s') % etype)
   541             self.w(self.req._('no such entity type %s') % etype)
   525             return
   542             return
   526         self.initialize_varmaker()
   543         self.initialize_varmaker()
   527         entity = cls(self.req)
   544         entity = cls(self.req)
   528         entity.eid = self.varmaker.next()
   545         entity.eid = self.varmaker.next()
   529         self.render_form(entity, peid, rtype, role, i18nctx, **kwargs)
   546         return entity
       
   547 
       
   548     def call(self, i18nctx, **kwargs):
       
   549         self.render_form(i18nctx, **kwargs)
       
   550 
       
   551 
       
   552 class InlineAddNewLinkView(InlineEntityCreationFormView):
       
   553     """
       
   554     :attr card: the cardinality of the relation according to role of `peid`
       
   555     """
       
   556     id = 'inline-addnew-link'
       
   557     __select__ = (match_kwargs('peid', 'rtype')
       
   558                   & specified_etype_implements('Any'))
       
   559 
       
   560     _select_attrs = InlineEntityCreationFormView._select_attrs + ('card',)
       
   561     form = None # no actual form wrapped
       
   562 
       
   563     def call(self, i18nctx, **kwargs):
       
   564         divid = "addNew%s%s%s:%s" % (self.etype, self.rtype, self.role, self.peid)
       
   565         self.w(u'<div class="inlinedform" id="%s" cubicweb:limit="true">'
       
   566           % divid)
       
   567         js = "addInlineCreationForm('%s', '%s', '%s', '%s', '%s')" % (
       
   568             self.peid, self.etype, self.rtype, self.role, i18nctx)
       
   569         if self.pform.should_hide_add_new_relation_link(self.rtype, self.card):
       
   570             js = "toggleVisibility('%s'); %s" % (divid, js)
       
   571         __ = self.req.pgettext
       
   572         self.w(u'<a class="addEntity" id="add%s:%slink" href="javascript: %s" >+ %s.</a>'
       
   573           % (self.rtype, self.peid, js, __(i18nctx, 'add a %s' % self.etype)))
       
   574         self.w(u'</div>')
       
   575         self.w(u'<div class="trame_grise">&#160;</div>')