web/views/editforms.py
branchstable
changeset 3744 767b5d0cd3cc
parent 3742 20f429eb5f46
child 3745 006c81b94ec5
equal deleted inserted replaced
3743:4b683fe21160 3744:767b5d0cd3cc
    17 from logilab.common.decorators import cached
    17 from logilab.common.decorators import cached
    18 
    18 
    19 from cubicweb import neg_role
    19 from cubicweb import neg_role
    20 from cubicweb.selectors import (match_kwargs, one_line_rset, non_final_entity,
    20 from cubicweb.selectors import (match_kwargs, one_line_rset, non_final_entity,
    21                                 specified_etype_implements, yes)
    21                                 specified_etype_implements, yes)
    22 from cubicweb.utils import make_uid
       
    23 from cubicweb.view import EntityView
    22 from cubicweb.view import EntityView
    24 from cubicweb.common import tags
    23 from cubicweb.common import tags
    25 from cubicweb.web import INTERNAL_FIELD_VALUE, RequestError, stdmsgs, eid_param
    24 from cubicweb.web import stdmsgs, eid_param
    26 from cubicweb.web import uicfg
    25 from cubicweb.web import uicfg
    27 from cubicweb.web.form import FormViewMixIn, FieldNotFound
    26 from cubicweb.web.form import FormViewMixIn, FieldNotFound
    28 from cubicweb.web.formfields import guess_field
    27 from cubicweb.web.formfields import guess_field
    29 from cubicweb.web.formwidgets import Button, SubmitButton, ResetButton
    28 from cubicweb.web.formwidgets import Button, SubmitButton, ResetButton
    30 from cubicweb.web.views import forms
    29 from cubicweb.web.views import forms
   135         return self.vreg['formrenderers'].select(
   134         return self.vreg['formrenderers'].select(
   136             'base', self.req, entity=entity, display_label=False,
   135             'base', self.req, entity=entity, display_label=False,
   137             display_help=False, display_fields=[(rtype, role)], table_class='',
   136             display_help=False, display_fields=[(rtype, role)], table_class='',
   138             button_bar_class='buttonbar', display_progress_div=False)
   137             button_bar_class='buttonbar', display_progress_div=False)
   139 
   138 
   140     def _build_form(self, entity, rtype, role, formid, default, reload,
   139     def _build_args(self, entity, rtype, role, formid, default, reload, lzone,
       
   140                     extradata=None):
       
   141         divid = '%s-%s-%s' % (entity.eid, rtype, role)
       
   142         event_args = {'divid' : divid, 'eid' : entity.eid, 'rtype' : rtype,
       
   143                       'reload' : dumps(reload), 'default' : default, 'role' : role, 'vid' : u'',
       
   144                       'lzone' : lzone}
       
   145         if extradata:
       
   146             event_args.update(extradata)
       
   147         return divid, event_args
       
   148 
       
   149     def _build_form(self, entity, rtype, role, formid, default, reload, lzone,
   141                   extradata=None, **formargs):
   150                   extradata=None, **formargs):
   142         divid = '%s-%s-%s' % (entity.eid, rtype, role)
   151         divid, event_args = self._build_args(entity, rtype, role, formid, default,
   143         event_data = {'divid' : divid, 'eid' : entity.eid, 'rtype' : rtype,
   152                                       reload, lzone, extradata)
   144                       'reload' : dumps(reload), 'default' : default, 'role' : role, 'vid' : u'',
   153         onsubmit = self._onsubmit % event_args
   145                       'lzone' : self._build_landing_zone(None)}
       
   146         if extradata:
       
   147             event_data.update(extradata)
       
   148         onsubmit = self._onsubmit % event_data
       
   149         cancelclick = self._cancelclick % (entity.eid, rtype, divid)
   154         cancelclick = self._cancelclick % (entity.eid, rtype, divid)
   150         form = self.vreg['forms'].select(
   155         form = self.vreg['forms'].select(
   151             formid, self.req, entity=entity, domid='%s-form' % divid,
   156             formid, self.req, entity=entity, domid='%s-form' % divid,
   152             cssstyle='display: none', onsubmit=onsubmit, action='#',
   157             cssstyle='display: none', onsubmit=onsubmit, action='#',
   153             form_buttons=[SubmitButton(), Button(stdmsgs.BUTTON_CANCEL,
   158             form_buttons=[SubmitButton(), Button(stdmsgs.BUTTON_CANCEL,
   154                                                  onclick=cancelclick)],
   159                                                  onclick=cancelclick)],
   155             **formargs)
   160             **formargs)
   156         form.event_data = event_data
   161         form.event_args = event_args
   157         return form
   162         return form
   158 
   163 
   159     def cell_call(self, row, col, rtype=None, role='subject',
   164     def cell_call(self, row, col, rtype=None, role='subject',
   160                   reload=False,      # controls reloading the whole page after change
   165                   reload=False,      # controls reloading the whole page after change
   161                   rvid=None,         # vid to be applied to other side of rtype (non final relations only)
   166                   rvid=None,         # vid to be applied to other side of rtype (non final relations only)
   164                                      # (esp. needed when values are links)
   169                                      # (esp. needed when values are links)
   165                   ):
   170                   ):
   166         """display field to edit entity's `rtype` relation on click"""
   171         """display field to edit entity's `rtype` relation on click"""
   167         assert rtype
   172         assert rtype
   168         assert role in ('subject', 'object'), '%s is not an acceptable role value' % role
   173         assert role in ('subject', 'object'), '%s is not an acceptable role value' % role
       
   174         self.req.add_js('cubicweb.edition.js')
       
   175         self.req.add_css('cubicweb.form.css')
   169         if default is None:
   176         if default is None:
   170             default = xml_escape(self.req._('<no value>'))
   177             default = xml_escape(self.req._('<no value>'))
   171         entity = self.entity(row, col)
   178         entity = self.entity(row, col)
   172         rschema = entity.schema.rschema(rtype)
   179         rschema = entity.schema.rschema(rtype)
   173         lzone = self._build_landing_zone(landing_zone)
   180         lzone = self._build_landing_zone(landing_zone)
   174         # compute value, checking perms, build form
   181         # compute value, checking perms, build form
   175         if rschema.final:
   182         if rschema.final:
   176             form = self._build_form(entity, rtype, role, 'edition', default, reload,
   183             form = self._build_form(entity, rtype, role, 'edition', default, reload, lzone,
   177                                     attrcategories=self.attrcategories)
   184                                     attrcategories=self.attrcategories)
   178             if not self.should_edit_attribute(entity, rschema, role, form):
   185             if not self.should_edit_attribute(entity, rschema, role, form):
   179                 self.w(entity.printable_value(rtype))
   186                 self.w(entity.printable_value(rtype))
   180                 return
   187                 return
   181             value = entity.printable_value(rtype) or default
   188             value = entity.printable_value(rtype) or default
   191                 value = default
   198                 value = default
   192             if not self.should_edit_relation(entity, rschema, role, rvid):
   199             if not self.should_edit_relation(entity, rschema, role, rvid):
   193                 if rset:
   200                 if rset:
   194                     self.w(value)
   201                     self.w(value)
   195                 return
   202                 return
   196             form = self._build_form(entity, rtype, role, 'base', default, reload,
   203             form = self._build_form(entity, rtype, role, 'base', default, reload, lzone,
   197                                     dict(vid=rvid, lzone=lzone))
   204                                     dict(vid=rvid, lzone=lzone))
   198             field = guess_field(entity.e_schema, entity.schema.rschema(rtype), role)
   205             field = guess_field(entity.e_schema, entity.schema.rschema(rtype), role)
   199             form.append_field(field)
   206             form.append_field(field)
   200             self.relation_form(lzone, value, form,
   207             self.relation_form(lzone, value, form,
   201                                self._build_renderer(entity, rtype, role))
   208                                self._build_renderer(entity, rtype, role))
   203     def should_edit_attribute(self, entity, rschema, role, form):
   210     def should_edit_attribute(self, entity, rschema, role, form):
   204         rtype = str(rschema)
   211         rtype = str(rschema)
   205         ttype = rschema.targets(entity.id, role)[0]
   212         ttype = rschema.targets(entity.id, role)[0]
   206         afs = uicfg.autoform_section.etype_get(entity.id, rtype, role, ttype)
   213         afs = uicfg.autoform_section.etype_get(entity.id, rtype, role, ttype)
   207         if not (afs in self.attrcategories and entity.has_perm('update')):
   214         if not (afs in self.attrcategories and entity.has_perm('update')):
   208             self.w(entity.printable_value(rtype))
       
   209             return False
   215             return False
   210         try:
   216         try:
   211             field = form.field_by_name(rtype, role)
   217             form.field_by_name(rtype, role)
   212         except FieldNotFound:
   218         except FieldNotFound:
   213             self.w(entity.printable_value(rtype))
       
   214             return False
   219             return False
   215         return True
   220         return True
   216 
   221 
   217     def should_edit_relation(self, entity, rschema, role, rvid):
   222     def should_edit_relation(self, entity, rschema, role, rvid):
   218         if ((role == 'subject' and not rschema.has_perm(self.req, 'add',
   223         if ((role == 'subject' and not rschema.has_perm(self.req, 'add',
   230               |   +-landing zone
   235               |   +-landing zone
   231               +-value
   236               +-value
   232               +-form-xxx div
   237               +-form-xxx div
   233         """
   238         """
   234         w = self.w
   239         w = self.w
   235         w(u'<div id="%s-reledit" class="field">' % form.event_data['divid'])
   240         w(u'<div id="%s-reledit" class="field">' % form.event_args['divid'])
   236         w(tags.div(lzone, klass='editableField', id=form.event_data['divid'],
   241         w(tags.div(lzone, klass='editableField', id=form.event_args['divid'],
   237                    onclick=self._onclick % form.event_data))
   242                    onclick=self._onclick % form.event_args))
   238         w(value)
   243         w(value)
   239         w(form.form_render(renderer=renderer))
   244         w(form.form_render(renderer=renderer))
   240         w(u'</div>')
   245         w(u'</div>')
   241 
   246 
   242 
   247 
       
   248 class DummyForm(object):
       
   249     __slots__ = ('event_args',)
       
   250     def form_render(self, **_args):
       
   251         return u''
       
   252     def append_field(self, *args):
       
   253         pass
       
   254 
   243 class AutoClickAndEditFormView(ClickAndEditFormView):
   255 class AutoClickAndEditFormView(ClickAndEditFormView):
   244     """same as ClickAndEditFormView but checking if the view *should* be applied
   256     """same as ClickAndEditFormView but checking if the view *should* be applied
   245     by checking uicfg configuration and composite relation property.
   257     by checking uicfg configuration and composite relation property.
   246     """
   258     """
   247     id = 'reledit'
   259     id = 'reledit'
       
   260     _onclick = (u"loadInlineEditionForm(%(eid)s, '%(rtype)s', '%(role)s', '%(eid)s', "
       
   261                 "'%(divid)s', %(reload)s, '%(vid)s', '%(default)s', '%(lzone)s');")
       
   262 
       
   263     def should_edit_attribute(self, entity, rschema, role, _form):
       
   264         rtype = str(rschema)
       
   265         ttype = rschema.targets(entity.id, role)[0]
       
   266         afs = uicfg.autoform_section.etype_get(entity.id, rtype, role, ttype)
       
   267         if not (afs in self.attrcategories and entity.has_perm('update')):
       
   268             return False
       
   269         return True
   248 
   270 
   249     def should_edit_relation(self, entity, rschema, role, rvid):
   271     def should_edit_relation(self, entity, rschema, role, rvid):
   250         eschema = entity.e_schema
   272         eschema = entity.e_schema
   251         rtype = str(rschema)
   273         rtype = str(rschema)
   252         # XXX check autoform_section. what if 'generic'?
   274         # XXX check autoform_section. what if 'generic'?
   259             self.wview(rvid, entity.related(rtype, role), 'null')
   281             self.wview(rvid, entity.related(rtype, role), 'null')
   260             return False
   282             return False
   261         return super(AutoClickAndEditFormView, self).should_edit_relation(
   283         return super(AutoClickAndEditFormView, self).should_edit_relation(
   262             entity, rschema, role, rvid)
   284             entity, rschema, role, rvid)
   263 
   285 
       
   286     def _build_form(self, entity, rtype, role, formid, default, reload, lzone,
       
   287                   extradata=None, **formargs):
       
   288         _divid, event_args = self._build_args(entity, rtype, role, formid, default,
       
   289                                               reload, lzone, extradata)
       
   290         form = DummyForm()
       
   291         form.event_args = event_args
       
   292         return form
       
   293 
       
   294     def _build_renderer(self, entity, rtype, role):
       
   295         pass
   264 
   296 
   265 class EditionFormView(FormViewMixIn, EntityView):
   297 class EditionFormView(FormViewMixIn, EntityView):
   266     """display primary entity edition form"""
   298     """display primary entity edition form"""
   267     id = 'edition'
   299     id = 'edition'
   268     # add yes() so it takes precedence over deprecated views in baseforms,
   300     # add yes() so it takes precedence over deprecated views in baseforms,