web/views/editforms.py
changeset 3524 a3431f4e2f40
parent 3485 e867ae952fc0
parent 3518 11ce4682187d
child 3536 f6c9a5df80fb
equal deleted inserted replaced
3505:c0c7a944c00d 3524:a3431f4e2f40
    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
    64                 continue
    65                 continue
    65             done.add(entity.eid)
    66             done.add(entity.eid)
    66             subform = self._cw.vreg['forms'].select('base', self._cw,
    67             subform = self._cw.vreg['forms'].select('base', self._cw,
    67                                                     entity=entity,
    68                                                     entity=entity,
    68                                                     mainform=False)
    69                                                     mainform=False)
    69             self.form_add_subform(subform)
    70             self.add_subform(subform)
    70 
    71 
    71 
    72 
    72 class DeleteConfFormView(FormViewMixIn, EntityView):
    73 class DeleteConfFormView(FormViewMixIn, EntityView):
    73     """form used to confirm deletion of some entities"""
    74     """form used to confirm deletion of some entities"""
    74     __regid__ = 'deleteconf'
    75     __regid__ = 'deleteconf'
   416                                                  rset=self.cw_rset, row=row,
   417                                                  rset=self.cw_rset, row=row,
   417                                                  formtype='muledit',
   418                                                  formtype='muledit',
   418                                                  mainform=False)
   419                                                  mainform=False)
   419             # XXX rely on the EntityCompositeFormRenderer to put the eid input
   420             # XXX rely on the EntityCompositeFormRenderer to put the eid input
   420             form.remove_field(form.field_by_name('eid'))
   421             form.remove_field(form.field_by_name('eid'))
   421             self.form_add_subform(form)
   422             self.add_subform(form)
   422 
   423 
   423 
   424 
   424 class TableEditFormView(FormViewMixIn, EntityView):
   425 class TableEditFormView(FormViewMixIn, EntityView):
   425     __regid__ = 'muledit'
   426     __regid__ = 'muledit'
   426     __select__ = EntityView.__select__ & yes()
   427     __select__ = EntityView.__select__ & yes()
   434         form = self._cw.vreg['forms'].select(self.__regid__, self._cw, rset=self.cw_rset)
   435         form = self._cw.vreg['forms'].select(self.__regid__, self._cw, rset=self.cw_rset)
   435         self.w(form.form_render())
   436         self.w(form.form_render())
   436 
   437 
   437 
   438 
   438 class InlineEntityEditionFormView(FormViewMixIn, EntityView):
   439 class InlineEntityEditionFormView(FormViewMixIn, EntityView):
       
   440     """
       
   441     :attr peid: the parent entity's eid hosting the inline form
       
   442     :attr rtype: the relation bridging `etype` and `peid`
       
   443     :attr role: the role played by the `peid` in the relation
       
   444     :attr pform: the parent form where this inlined form is being displayed
       
   445     """
   439     __regid__ = 'inline-edition'
   446     __regid__ = 'inline-edition'
   440     __select__ = non_final_entity() & match_kwargs('peid', 'rtype')
   447     __select__ = non_final_entity() & match_kwargs('peid', 'rtype')
       
   448 
       
   449     _select_attrs = ('peid', 'rtype', 'role', 'pform')
   441     removejs = "removeInlinedEntity('%s', '%s', '%s')"
   450     removejs = "removeInlinedEntity('%s', '%s', '%s')"
   442 
   451 
   443     def call(self, **kwargs):
   452     def __init__(self, *args, **kwargs):
   444         """redefine default call() method to avoid automatic
   453         for attr in self._select_attrs:
   445         insertions of <div class="section"> between each row of
   454             setattr(self, attr, kwargs.pop(attr, None))
   446         the resultset
   455         super(InlineEntityEditionFormView, self).__init__(*args, **kwargs)
   447         """
   456 
   448         rset = self.cw_rset
   457     def _entity(self):
   449         for i in xrange(len(rset)):
   458         assert self.cw_row is not None, self
   450             self.wview(self.__regid__, rset, row=i, **kwargs)
   459         return self.cw_rset.get_entity(self.cw_row, self.cw_col)
   451 
   460 
   452     def cell_call(self, row, col, peid, rtype, role, i18nctx, **kwargs):
   461     @property
       
   462     @cached
       
   463     def form(self):
       
   464         entity = self._entity()
       
   465         form = self.vreg['forms'].select('edition', self._cw,
       
   466                                          entity=entity,
       
   467                                          form_renderer_id='inline',
       
   468                                          mainform=False, copy_nav_params=False,
       
   469                                          **self.extra_kwargs)
       
   470         form.parent_form = self.pform
       
   471         self.add_hiddens(form, entity)
       
   472         return form
       
   473 
       
   474     def cell_call(self, row, col, i18nctx, **kwargs):
   453         """
   475         """
   454         :param peid: the parent entity's eid hosting the inline form
   476         :param peid: the parent entity's eid hosting the inline form
   455         :param rtype: the relation bridging `etype` and `peid`
   477         :param rtype: the relation bridging `etype` and `peid`
   456         :param role: the role played by the `peid` in the relation
   478         :param role: the role played by the `peid` in the relation
   457         """
   479         """
   458         entity = self.cw_rset.get_entity(row, col)
   480         entity = self._entity()
   459         divonclick = "restoreInlinedEntity('%s', '%s', '%s')" % (peid, rtype,
   481         divonclick = "restoreInlinedEntity('%s', '%s', '%s')" % (
   460                                                                  entity.eid)
   482             self.peid, self.rtype, entity.eid)
   461         self.render_form(entity, peid, rtype, role, i18nctx,
   483         self.render_form(i18nctx, divonclick=divonclick, **kwargs)
   462                          divonclick=divonclick)
   484 
   463 
   485     def render_form(self, i18nctx, **kwargs):
   464     def render_form(self, entity, peid, rtype, role, i18nctx, **kwargs):
       
   465         """fetch and render the form"""
   486         """fetch and render the form"""
   466         form = self._cw.vreg['forms'].select('edition', self._cw, entity=entity,
   487         entity = self._entity()
   467                                              form_renderer_id='inline',
   488         divid = '%s-%s-%s' % (self.peid, self.rtype, entity.eid)
   468                                              formtype='inlined',
   489         title = self.req.pgettext(i18nctx, 'This %s' % entity.e_schema)
   469                                              mainform=False,
   490         removejs = self.removejs % (self.peid, self.rtype, entity.eid)
   470                                              copy_nav_params=False)
   491         countkey = '%s_count' % self.rtype
   471         self.add_hiddens(form, entity, peid, rtype, role)
       
   472         divid = '%s-%s-%s' % (peid, rtype, entity.eid)
       
   473         title = self._cw.pgettext(i18nctx, 'This %s' % entity.e_schema)
       
   474         removejs = self.removejs % (peid, rtype, entity.eid)
       
   475         countkey = '%s_count' % rtype
       
   476         try:
   492         try:
   477             self._cw.data[countkey] += 1
   493             self._cw.data[countkey] += 1
   478         except:
   494         except:
   479             self._cw.data[countkey] = 1
   495             self._cw.data[countkey] = 1
   480         self.w(form.form_render(divid=divid, title=title, removejs=removejs,
   496         self.w(self.form.form_render(
   481                                 i18nctx=i18nctx,
   497             divid=divid, title=title, removejs=removejs, i18nctx=i18nctx,
   482                                 counter=self._cw.data[countkey], **kwargs))
   498             counter=self.req.data[countkey], **kwargs))
   483 
   499 
   484     def add_hiddens(self, form, entity, peid, rtype, role):
   500     def add_hiddens(self, form, entity):
   485         # to ease overriding (see cubes.vcsfile.views.forms for instance)
   501         # to ease overriding (see cubes.vcsfile.views.forms for instance)
   486         form.form_add_hidden(name='%s:%s' % (rtype, peid), value=entity.eid,
   502         if self.keep_entity(form, entity):
   487                              id='rel-%s-%s-%s'  % (peid, rtype, entity.eid))
   503             if entity.has_eid():
   488 
   504                 rval = entity.eid
   489     def keep_entity(self, form, entity, peid, rtype):
   505             else:
       
   506                 rval = INTERNAL_FIELD_VALUE
       
   507             form.form_add_hidden('edit%s-%s:%s' % (self.role[0], self.rtype, self.peid), rval)
       
   508         form.form_add_hidden(name='%s:%s' % (self.rtype, self.peid), value=entity.eid,
       
   509                              id='rel-%s-%s-%s'  % (self.peid, self.rtype, entity.eid))
       
   510 
       
   511     def keep_entity(self, form, entity):
   490         if not entity.has_eid():
   512         if not entity.has_eid():
   491             return True
   513             return True
   492         # are we regenerating form because of a validation error ?
   514         # are we regenerating form because of a validation error ?
   493         if form.form_previous_values:
   515         if form.form_previous_values:
   494             cdvalues = self._cw.list_form_param(eid_param(rtype, peid),
   516             cdvalues = self._cw.list_form_param(eid_param(self.rtype, self.peid),
   495                                                 form.form_previous_values)
   517                                                 form.form_previous_values)
   496             if unicode(entity.eid) not in cdvalues:
   518             if unicode(entity.eid) not in cdvalues:
   497                 return False
   519                 return False
   498         return True
   520         return True
   499 
   521 
   500 
   522 
   501 class InlineEntityCreationFormView(InlineEntityEditionFormView):
   523 class InlineEntityCreationFormView(InlineEntityEditionFormView):
       
   524     """
       
   525     :attr etype: the entity type being created in the inline form
       
   526     """
   502     __regid__ = 'inline-creation'
   527     __regid__ = 'inline-creation'
   503     __select__ = (match_kwargs('peid', 'rtype')
   528     __select__ = (match_kwargs('peid', 'rtype')
   504                   & specified_etype_implements('Any'))
   529                   & specified_etype_implements('Any'))
       
   530     _select_attrs = InlineEntityEditionFormView._select_attrs + ('etype',)
   505     removejs = "removeInlineForm('%s', '%s', '%s')"
   531     removejs = "removeInlineForm('%s', '%s', '%s')"
   506 
   532 
   507     def call(self, etype, peid, rtype, role, i18nctx, **kwargs):
   533     @cached
   508         """
   534     def _entity(self):
   509         :param etype: the entity type being created in the inline form
       
   510         :param peid: the parent entity's eid hosting the inline form
       
   511         :param rtype: the relation bridging `etype` and `peid`
       
   512         :param role: the role played by the `peid` in the relation
       
   513         """
       
   514         try:
   535         try:
   515             cls = self._cw.vreg['etypes'].etype_class(etype)
   536             cls = self._cw.vreg['etypes'].etype_class(self.etype)
   516         except:
   537         except:
   517             self.w(self._cw._('no such entity type %s') % etype)
   538             self.w(self._cw._('no such entity type %s') % etype)
   518             return
   539             return
   519         entity = cls(self._cw)
   540         self.initialize_varmaker()
   520         entity.eid = self._cw.varmaker.next()
   541         entity = cls(self.req)
   521         self.render_form(entity, peid, rtype, role, i18nctx, **kwargs)
   542         entity.eid = self.varmaker.next()
       
   543         return entity
       
   544 
       
   545     def call(self, i18nctx, **kwargs):
       
   546         self.render_form(i18nctx, **kwargs)
       
   547 
       
   548 
       
   549 class InlineAddNewLinkView(InlineEntityCreationFormView):
       
   550     """
       
   551     :attr card: the cardinality of the relation according to role of `peid`
       
   552     """
       
   553     __regid__ = 'inline-addnew-link'
       
   554     __select__ = (match_kwargs('peid', 'rtype')
       
   555                   & specified_etype_implements('Any'))
       
   556 
       
   557     _select_attrs = InlineEntityCreationFormView._select_attrs + ('card',)
       
   558     form = None # no actual form wrapped
       
   559 
       
   560     def call(self, i18nctx, **kwargs):
       
   561         divid = "addNew%s%s%s:%s" % (self.etype, self.rtype, self.role, self.peid)
       
   562         self.w(u'<div class="inlinedform" id="%s" cubicweb:limit="true">'
       
   563           % divid)
       
   564         js = "addInlineCreationForm('%s', '%s', '%s', '%s', '%s')" % (
       
   565             self.peid, self.etype, self.rtype, self.role, i18nctx)
       
   566         if self.pform.should_hide_add_new_relation_link(self.rtype, self.card):
       
   567             js = "toggleVisibility('%s'); %s" % (divid, js)
       
   568         __ = self.req.pgettext
       
   569         self.w(u'<a class="addEntity" id="add%s:%slink" href="javascript: %s" >+ %s.</a>'
       
   570           % (self.rtype, self.peid, js, __(i18nctx, 'add a %s' % self.etype)))
       
   571         self.w(u'</div>')
       
   572         self.w(u'<div class="trame_grise">&#160;</div>')