web/views/editforms.py
changeset 3777 3ef8cdb5fb1c
parent 3720 5376aaadd16b
parent 3767 03924de0014d
child 3890 d7a270f50f54
--- a/web/views/editforms.py	Mon Oct 19 20:22:01 2009 +0200
+++ b/web/views/editforms.py	Wed Oct 21 17:32:20 2009 +0200
@@ -19,10 +19,9 @@
 from cubicweb import neg_role
 from cubicweb.selectors import (match_kwargs, one_line_rset, non_final_entity,
                                 specified_etype_implements, yes)
-from cubicweb.utils import make_uid
 from cubicweb.view import EntityView
 from cubicweb.common import tags
-from cubicweb.web import INTERNAL_FIELD_VALUE, RequestError, stdmsgs, eid_param
+from cubicweb.web import stdmsgs, eid_param
 from cubicweb.web import uicfg
 from cubicweb.web.form import FormViewMixIn, FieldNotFound
 from cubicweb.web.formfields import guess_field
@@ -111,14 +110,103 @@
     # FIXME editableField class could be toggleable from userprefs
 
     _onclick = u"showInlineEditionForm(%(eid)s, '%(rtype)s', '%(divid)s')"
-    _defaultlandingzone = (u'<img title="%(msg)s" '
-                           'src="data/accessories-text-editor.png" '
+    _onsubmit = ("return inlineValidateRelationForm('%(rtype)s', '%(role)s', '%(eid)s', "
+                 "'%(divid)s', %(reload)s, '%(vid)s', '%(default)s', '%(lzone)s');")
+    _cancelclick = "hideInlineEdit(%s,\'%s\',\'%s\')"
+    _defaultlandingzone = (u'<img title="%(msg)s" src="data/file.gif" '
                            'alt="%(msg)s"/>')
     _landingzonemsg = _('click to edit this field')
     # default relation vids according to cardinality
     _one_rvid = 'incontext'
     _many_rvid = 'csv'
 
+
+    def cell_call(self, row, col, rtype=None, role='subject',
+                  reload=False,      # controls reloading the whole page after change
+                  rvid=None,         # vid to be applied to other side of rtype (non final relations only)
+                  default=None,      # default value
+                  landing_zone=None  # prepend value with a separate html element to click onto
+                                     # (esp. needed when values are links)
+                  ):
+        """display field to edit entity's `rtype` relation on click"""
+        assert rtype
+        assert role in ('subject', 'object'), '%s is not an acceptable role value' % role
+        self.req.add_js('cubicweb.edition.js')
+        self.req.add_css('cubicweb.form.css')
+        if default is None:
+            default = xml_escape(self._cw._('<no value>'))
+        schema = self._cw.vreg.schema
+        entity = self.cw_rset.get_entity(row, col)
+        rschema = schema.rschema(rtype)
+        lzone = self._build_landing_zone(landing_zone)
+        # compute value, checking perms, build form
+        if rschema.final:
+            form = self._build_form(entity, rtype, role, 'edition', default, reload, lzone)
+            if not self.should_edit_attribute(entity, rschema, role, form):
+                self.w(entity.printable_value(rtype))
+                return
+            value = entity.printable_value(rtype) or default
+            self.relation_form(lzone, value, form,
+                               self._build_renderer(entity, rtype, role))
+        else:
+            if rvid is None:
+                rvid = self._compute_best_vid(entity.e_schema, rschema, role)
+            rset = entity.related(rtype, role)
+            if rset:
+                value = self._cw.view(rvid, rset)
+            else:
+                value = default
+            if not self.should_edit_relation(entity, rschema, role, rvid):
+                if rset:
+                    self.w(value)
+                return
+            form = self._build_form(entity, rtype, role, 'base', default, reload, lzone,
+                                    dict(vid=rvid, lzone=lzone))
+            field = guess_field(entity.e_schema, entity.schema.rschema(rtype), role)
+            form.append_field(field)
+            self.relation_form(lzone, value, form,
+                               self._build_renderer(entity, rtype, role))
+
+    def should_edit_attribute(self, entity, rschema, role, form):
+        rtype = str(rschema)
+        ttype = rschema.targets(entity.id, role)[0]
+        afs = uicfg.autoform_section.etype_get(entity.id, rtype, role, ttype)
+        if 'main_hidden' in afs or not entity.has_perm('update'):
+            return False
+        try:
+            form.field_by_name(rtype, role)
+        except FieldNotFound:
+            return False
+        return True
+
+    def should_edit_relation(self, entity, rschema, role, rvid):
+        if ((role == 'subject' and not rschema.has_perm(self._cw, 'add',
+                                                        fromeid=entity.eid))
+            or
+            (role == 'object' and not rschema.has_perm(self._cw, 'add',
+                                                       toeid=entity.eid))):
+            return False
+        return True
+
+    def relation_form(self, lzone, value, form, renderer):
+        """xxx-reledit div (class=field)
+              +-xxx div (class="editableField")
+              |   +-landing zone
+              +-xxx-value div
+              +-xxx-form div
+        """
+        w = self.w
+        divid = form.event_args['divid']
+        w(u'<div id="%s-reledit" class="field">' % form.event_args['divid'])
+        w(u'<div id="%s" class="editableField" onclick="%s" title="%s">' % (
+                divid, xml_escape(self._onclick % form.event_args),
+                self.req._(self._landingzonemsg)))
+        w(lzone)
+        w(u'</div>')
+        w(u'<div id="%s-value" class="editableFieldValue">%s</div>' % (divid, value))
+        w(form.form_render(renderer=renderer))
+        w(u'</div>')
+
     def _compute_best_vid(self, eschema, rschema, role):
         if eschema.cardinality(rschema, role) in '+*':
             return self._many_rvid
@@ -134,139 +222,45 @@
             display_help=False, table_class='',
             button_bar_class='buttonbar', display_progress_div=False)
 
-    def _build_form(self, entity, rtype, role, default, onsubmit, reload,
-                  extradata=None, **formargs):
-        divid = 'd%s' % make_uid('%s-%s' % (rtype, entity.eid))
-        event_data = {'divid' : divid, 'eid' : entity.eid, 'rtype' : rtype,
-                      'reload' : dumps(reload), 'default' : default}
+    def _build_args(self, entity, rtype, role, formid, default, reload, lzone,
+                    extradata=None):
+        divid = '%s-%s-%s' % (rtype, role, entity.eid)
+        event_args = {'divid' : divid, 'eid' : entity.eid, 'rtype' : rtype,
+                      'reload' : dumps(reload), 'default' : default, 'role' : role, 'vid' : u'',
+                      'lzone' : lzone}
         if extradata:
-            event_data.update(extradata)
-        onsubmit %= event_data
-        cancelclick = "hideInlineEdit(%s,\'%s\',\'%s\')" % (entity.eid, rtype,
-                                                            divid)
+            event_args.update(extradata)
+        return divid, event_args
+
+    def _build_form(self, entity, rtype, role, formid, default, reload, lzone,
+                  extradata=None, **formargs):
+        divid, event_args = self._build_args(entity, rtype, role, formid, default,
+                                      reload, lzone, extradata)
+        onsubmit = self._onsubmit % event_args
+        cancelclick = self._cancelclick % (entity.eid, rtype, divid)
         form = self._cw.vreg['forms'].select(
-            'edition', self._cw, entity=entity, domid='%s-form' % divid,
+            formid, self._cw, entity=entity, domid='%s-form' % divid,
             cssstyle='display: none', onsubmit=onsubmit, action='#',
-            display_fields=[(rtype, role)],
             form_buttons=[SubmitButton(), Button(stdmsgs.BUTTON_CANCEL,
                                                  onclick=cancelclick)],
             **formargs)
-        form.event_data = event_data
+        form.event_args = event_args
         return form
 
-    def cell_call(self, row, col, rtype=None, role='subject',
-                  reload=False,      # controls reloading the whole page after change
-                  rvid=None,         # vid to be applied to other side of rtype (non final relations only)
-                  default=None,      # default value
-                  landing_zone=None  # prepend value with a separate html element to click onto
-                                     # (esp. needed when values are links)
-                  ):
-        """display field to edit entity's `rtype` relation on click"""
-        assert rtype
-        assert role in ('subject', 'object')
-        if default is None:
-            default = xml_escape(self._cw._('<no value>'))
-        schema = self._cw.vreg.schema
-        entity = self.cw_rset.get_entity(row, col)
-        rschema = schema.rschema(rtype)
-        lzone = self._build_landing_zone(landing_zone)
-        # compute value, checking perms, build form
-        if rschema.final:
-            onsubmit = ("return inlineValidateAttributeForm('%(rtype)s', '%(eid)s', '%(divid)s', "
-                        "%(reload)s, '%(default)s');")
-            form = self._build_form(
-                entity, rtype, role, default, onsubmit, reload)
-            if not self.should_edit_attribute(entity, rschema, role, form):
-                self.w(entity.printable_value(rtype))
-                return
-            value = entity.printable_value(rtype) or default
-            self.attribute_form(lzone, value, form,
-                                 self._build_renderer(entity, rtype, role))
-        else:
-            if rvid is None:
-                rvid = self._compute_best_vid(entity.e_schema, rschema, role)
-            rset = entity.related(rtype, role)
-            if rset:
-                value = self._cw.view(rvid, rset)
-            else:
-                value = default
-            if not self.should_edit_relation(entity, rschema, role, rvid):
-                if rset:
-                    self.w(value)
-                return
-            onsubmit = ("return inlineValidateRelationForm('%(rtype)s', '%(role)s', '%(eid)s', "
-                        "'%(divid)s', %(reload)s, '%(vid)s', '%(default)s', '%(lzone)s');")
-            form = self._build_form(
-                entity, rtype, role, default, onsubmit, reload,
-                dict(vid=rvid, role=role, lzone=lzone))
-            self.relation_form(lzone, value, form,
-                               self._build_renderer(entity, rtype, role))
-
-    def should_edit_attribute(self, entity, rschema, role, form):
-        rtype = str(rschema)
-        ttype = rschema.targets(entity.__regid__, role)[0]
-        afs = uicfg.autoform_section.etype_get(entity.__regid__, rtype, role, ttype)
-        if 'main_hidden' in afs or not entity.has_perm('update'):
-            self.w(entity.printable_value(rtype))
-            return False
-        try:
-            field = form.field_by_name(rtype, role)
-        except FieldNotFound:
-            self.w(entity.printable_value(rtype))
-            return False
-        return True
-
-    def should_edit_relation(self, entity, rschema, role, rvid):
-        if ((role == 'subject' and not rschema.has_perm(self._cw, 'add',
-                                                        fromeid=entity.eid))
-            or
-            (role == 'object' and not rschema.has_perm(self._cw, 'add',
-                                                       toeid=entity.eid))):
-            self.wview(rvid, entity.related(str(rschema), role), 'null')
-            return False
-        return True
-
-    def attribute_form(self, lzone, value, form, renderer):
-        """div (class=field)
-              +-xxx div
-              |  +-xxx div (class=editableField)
-              |  |  +-landing zone
-              |  +-value-xxx div
-              |     +-value
-              +-form-xxx div
-        """
-        w = self.w
-        w(u'<div class="field">')
-        w(u'<div id="%s" style="display: inline">' % form.event_data['divid'])
-        w(tags.div(lzone, klass='editableField',
-                   onclick=self._onclick % form.event_data))
-        w(u'<div id="value-%s" style="display: inline">%s</div>' %
-               (form.event_data['divid'], value))
-        w(u'</div>')
-        w(form.form_render(renderer=renderer))
-        w(u'</div>')
-
-    def relation_form(self, lzone, value, form, renderer):
-        """xxx-reledit div (class=field)
-              +-xxx div (class="editableField")
-              |   +-landing zone
-              +-value
-              +-form-xxx div
-        """
-        w = self.w
-        w(u'<div id="%s-reledit" class="field">' % form.event_data['divid'])
-        w(tags.div(lzone, klass='editableField', id=form.event_data['divid'],
-                   onclick=self._onclick % form.event_data))
-        w(value)
-        w(form.form_render(renderer=renderer))
-        w(u'</div>')
-
+class DummyForm(object):
+    __slots__ = ('event_args',)
+    def form_render(self, **_args):
+        return u''
+    def append_field(self, *args):
+        pass
 
 class AutoClickAndEditFormView(ClickAndEditFormView):
     """same as ClickAndEditFormView but checking if the view *should* be applied
     by checking uicfg configuration and composite relation property.
     """
     __regid__ = 'reledit'
+    _onclick = (u"loadInlineEditionForm(%(eid)s, '%(rtype)s', '%(role)s', "
+                "'%(divid)s', %(reload)s, '%(vid)s', '%(default)s', '%(lzone)s');")
 
     def should_edit_relation(self, entity, rschema, role, rvid):
         eschema = entity.e_schema
@@ -283,6 +277,16 @@
         return super(AutoClickAndEditFormView, self).should_edit_relation(
             entity, rschema, role, rvid)
 
+    def _build_form(self, entity, rtype, role, formid, default, reload, lzone,
+                  extradata=None, **formargs):
+        _divid, event_args = self._build_args(entity, rtype, role, formid, default,
+                                              reload, lzone, extradata)
+        form = DummyForm()
+        form.event_args = event_args
+        return form
+
+    def _build_renderer(self, entity, rtype, role):
+        pass
 
 class EditionFormView(FormViewMixIn, EntityView):
     """display primary entity edition form"""