# HG changeset patch # User Aurelien Campeas # Date 1295461197 -3600 # Node ID 0eed6045d785cb7628e7fa30a712a3a62f6d2f06 # Parent 5f8e52d722c58cf7788352a8201f69d9e5ccf847 [reledit] kill the reledit/doreledit duality * * * [reledit] use action to determine form content * * * [reledit] use self.entity instead of passing entity everywhere diff -r 5f8e52d722c5 -r 0eed6045d785 web/data/cubicweb.reledit.js --- a/web/data/cubicweb.reledit.js Thu Mar 10 12:04:46 2011 +0100 +++ b/web/data/cubicweb.reledit.js Wed Jan 19 19:19:57 2011 +0100 @@ -18,6 +18,7 @@ cleanupAfterCancel: function (divid) { jQuery('#appMsg').hide(); jQuery('div.errorMessage').remove(); + // plus re-set inline style ? jQuery('#' + divid).show(); jQuery('#' + divid + '-value').show(); jQuery('#' + divid + '-form').hide(); @@ -63,9 +64,9 @@ * @param reload: boolean to reload page if true (when changing URL dependant data) * @param default_value : value if the field is empty */ - loadInlineEditionForm: function(formid, eid, rtype, role, divid, reload, vid) { + loadInlineEditionForm: function(formid, eid, rtype, role, divid, reload, vid, action) { var args = {fname: 'reledit_form', rtype: rtype, role: role, - pageid: pageid, + pageid: pageid, action: action, eid: eid, divid: divid, formid: formid, reload: reload, vid: vid}; var d = jQuery('#'+divid+'-reledit').loadxhtml(JSON_BASE_URL, args, 'post'); diff -r 5f8e52d722c5 -r 0eed6045d785 web/views/basecontrollers.py --- a/web/views/basecontrollers.py Thu Mar 10 12:04:46 2011 +0100 +++ b/web/views/basecontrollers.py Wed Jan 19 19:19:57 2011 +0100 @@ -455,13 +455,13 @@ def js_reledit_form(self): req = self._cw args = dict((x, req.form[x]) - for x in ('formid', 'rtype', 'role', 'reload')) + for x in ('formid', 'rtype', 'role', 'reload', 'action')) rset = req.eid_rset(typed_eid(self._cw.form['eid'])) try: args['reload'] = json.loads(args['reload']) except ValueError: # not true/false, an absolute url assert args['reload'].startswith('http') - view = req.vreg['views'].select('doreledit', req, rset=rset, rtype=args['rtype']) + view = req.vreg['views'].select('reledit', req, rset=rset, rtype=args['rtype']) return self._call_view(view, **args) @jsonize diff -r 5f8e52d722c5 -r 0eed6045d785 web/views/reledit.py --- a/web/views/reledit.py Thu Mar 10 12:04:46 2011 +0100 +++ b/web/views/reledit.py Wed Jan 19 19:19:57 2011 +0100 @@ -15,7 +15,9 @@ # # You should have received a copy of the GNU Lesser General Public License along # with CubicWeb. If not, see . -"""the 'reedit' feature (eg edit attribute/relation from primary view""" +"""edit entity attributes/relations from any view, without going to the entity +form +""" __docformat__ = "restructuredtext en" _ = unicode @@ -24,7 +26,8 @@ from warnings import warn from logilab.mtconverter import xml_escape -from logilab.common.deprecation import deprecated +from logilab.common.deprecation import deprecated, class_renamed +from logilab.common.decorators import cached from cubicweb import neg_role from cubicweb.schema import display_name @@ -43,16 +46,18 @@ return u'' def append_field(self, *args): pass + def add_hidden(self, *args): + pass rctrl = uicfg.reledit_ctrl -class ClickAndEditFormView(EntityView): - __regid__ = 'doreledit' +class AutoClickAndEditFormView(EntityView): + __regid__ = 'reledit' __select__ = non_final_entity() & match_kwargs('rtype') # ui side continuations _onclick = (u"cw.reledit.loadInlineEditionForm('%(formid)s', %(eid)s, '%(rtype)s', '%(role)s', " - "'%(divid)s', %(reload)s, '%(vid)s');") + "'%(divid)s', %(reload)s, '%(vid)s', '%(action)s');") _cancelclick = "cw.reledit.cleanupAfterCancel('%s')" # ui side actions/buttons @@ -75,93 +80,84 @@ # function taking the subject entity & returning a boolean or an eid rvid=None, # vid to be applied to other side of rtype (non final relations only) default_value=None, - formid='base' + formid='base', + action=None ): """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._cw.add_css('cubicweb.form.css') self._cw.add_js(('cubicweb.reledit.js', 'cubicweb.edition.js', 'cubicweb.ajax.js')) entity = self.cw_rset.get_entity(row, col) rschema = self._cw.vreg.schema[rtype] - self._rules = rctrl.etype_get(entity.e_schema.type, rschema.type, role, '*') + self._rules = rctrl.etype_get(self.entity.e_schema.type, rschema.type, role, '*') if rvid is not None or default_value is not None: warn('[3.9] specifying rvid/default_value on select is deprecated, ' 'reledit_ctrl rtag to control this' % self, DeprecationWarning) - reload = self._compute_reload(entity, rschema, role, reload) - divid = self._build_divid(rtype, role, entity.eid) + reload = self._compute_reload(rschema, role, reload) + divid = self._build_divid(rtype, role, self.entity.eid) if rschema.final: - self._handle_attribute(entity, rschema, role, divid, reload) + self._handle_attribute(rschema, role, divid, reload, action) else: if self._is_composite(): - self._handle_composite(entity, rschema, role, divid, reload, formid) + self._handle_composite(rschema, role, divid, reload, formid, action) else: - self._handle_relation(entity, rschema, role, divid, reload, formid) + self._handle_relation(rschema, role, divid, reload, formid, action) - def _handle_attribute(self, entity, rschema, role, divid, reload): - rtype = rschema.type - value = entity.printable_value(rtype) - if not self._should_edit_attribute(entity, rschema): + def _handle_attribute(self, rschema, role, divid, reload, action): + value = self.entity.printable_value(rschema.type) + if not self._should_edit_attribute(rschema): self.w(value) return - display_label, related_entity = self._prepare_form(entity, rtype, role) - form, renderer = self._build_form(entity, rtype, role, divid, 'base', - reload, display_label, related_entity) + form, renderer = self._build_form(self.entity, rschema, role, divid, 'base', reload, action) value = value or self._compute_default_value(rschema, role) self.view_form(divid, value, form, renderer) - def _compute_formid_value(self, entity, rschema, role, rvid, formid): - related_rset = entity.related(rschema.type, role) + def _compute_formid_value(self, rschema, role, rvid, formid): + related_rset = self.entity.related(rschema.type, role) if related_rset: value = self._cw.view(rvid, related_rset) else: value = self._compute_default_value(rschema, role) - if not self._should_edit_relation(entity, rschema, role): + if not self._should_edit_relation(rschema, role): return None, value return formid, value - def _handle_relation(self, entity, rschema, role, divid, reload, formid): + def _handle_relation(self, rschema, role, divid, reload, formid, action): rvid = self._rules.get('rvid', 'autolimited') - formid, value = self._compute_formid_value(entity, rschema, role, rvid, formid) + formid, value = self._compute_formid_value(rschema, role, rvid, formid) if formid is None: return self.w(value) - rtype = rschema.type - display_label, related_entity = self._prepare_form(entity, rtype, role) - form, renderer = self._build_form(entity, rtype, role, divid, formid, reload, - display_label, related_entity, dict(vid=rvid)) + form, renderer = self._build_form(self.entity, rschema, role, divid, formid, + reload, action, dict(vid=rvid)) self.view_form(divid, value, form, renderer) - def _handle_composite(self, entity, rschema, role, divid, reload, formid): + def _handle_composite(self, rschema, role, divid, reload, formid, action): # this is for attribute-like composites (1 target type, 1 related entity at most, for now) - ttypes = self._compute_ttypes(rschema, role) + entity = self.entity related_rset = entity.related(rschema.type, role) - add_related = self._may_add_related(related_rset, entity, rschema, role, ttypes) - edit_related = self._may_edit_related_entity(related_rset, entity, rschema, role, ttypes) - delete_related = edit_related and self._may_delete_related(related_rset, entity, rschema, role) + add_related = self._may_add_related(related_rset, rschema, role) + edit_related = self._may_edit_related_entity(related_rset, rschema, role) + delete_related = edit_related and self._may_delete_related(related_rset, rschema, role) rvid = self._rules.get('rvid', 'autolimited') - formid, value = self._compute_formid_value(entity, rschema, role, rvid, formid) + formid, value = self._compute_formid_value(rschema, role, rvid, formid) if formid is None or not (edit_related or add_related): # till we learn to handle cases where not (edit_related or add_related) self.w(value) return - rtype = rschema.type - ttype = ttypes[0] - _fdata = self._prepare_composite_form(entity, rtype, role, edit_related, - add_related and ttype) - display_label, related_entity = _fdata - form, renderer = self._build_form(entity, rtype, role, divid, formid, reload, - display_label, related_entity, dict(vid=rvid)) + form, renderer = self._build_form(entity, rschema, role, divid, formid, + reload, action, dict(vid=rvid)) self.view_form(divid, value, form, renderer, edit_related, add_related, delete_related) + @cached def _compute_ttypes(self, rschema, role): dual_role = neg_role(role) return getattr(rschema, '%ss' % dual_role)() - def _compute_reload(self, entity, rschema, role, reload): + def _compute_reload(self, rschema, role, reload): ctrl_reload = self._rules.get('reload', reload) if callable(ctrl_reload): - ctrl_reload = ctrl_reload(entity) + ctrl_reload = ctrl_reload(self.entity) if isinstance(ctrl_reload, int) and ctrl_reload > 1: # not True/False ctrl_reload = self._cw.build_url(ctrl_reload) return ctrl_reload @@ -179,33 +175,36 @@ def _is_composite(self): return self._rules.get('edit_target') == 'related' - def _may_add_related(self, related_rset, entity, rschema, role, ttypes): + def _may_add_related(self, related_rset, rschema, role): """ ok for attribute-like composite entities """ + ttypes = self._compute_ttypes(rschema, role) if len(ttypes) > 1: # many etypes: learn how to do it return False - rdef = rschema.role_rdef(entity.e_schema, ttypes[0], role) + rdef = rschema.role_rdef(self.entity.e_schema, ttypes[0], role) card = rdef.role_cardinality(role) if related_rset or card not in '?1': return False if role == 'subject': - kwargs = {'fromeid': entity.eid} + kwargs = {'fromeid': self.entity.eid} else: - kwargs = {'toeid': entity.eid} + kwargs = {'toeid': self.entity.eid} return rdef.has_perm(self._cw, 'add', **kwargs) - def _may_edit_related_entity(self, related_rset, entity, rschema, role, ttypes): + def _may_edit_related_entity(self, related_rset, rschema, role): """ controls the edition of the related entity """ + ttypes = self._compute_ttypes(rschema, role) if len(ttypes) > 1 or len(related_rset.rows) != 1: return False - if entity.e_schema.rdef(rschema, role).role_cardinality(role) not in '?1': + if self.entity.e_schema.rdef(rschema, role).role_cardinality(role) not in '?1': return False return related_rset.get_entity(0, 0).cw_has_perm('update') - def _may_delete_related(self, related_rset, entity, rschema, role): + def _may_delete_related(self, related_rset, rschema, role): # we assume may_edit_related, only 1 related entity if not related_rset: return False rentity = related_rset.get_entity(0, 0) + entity = self.entity if role == 'subject': kwargs = {'fromeid': entity.eid, 'toeid': rentity.eid} else: @@ -230,33 +229,33 @@ """ builds an id for the root div of a reledit widget """ return '%s-%s-%s' % (rtype, role, entity_eid) - def _build_args(self, entity, rtype, role, formid, reload, + def _build_args(self, entity, rtype, role, formid, reload, action, extradata=None): divid = self._build_divid(rtype, role, entity.eid) event_args = {'divid' : divid, 'eid' : entity.eid, 'rtype' : rtype, 'formid': formid, - 'reload' : json_dumps(reload), + 'reload' : json_dumps(reload), 'action': action, 'role' : role, 'vid' : u''} if extradata: event_args.update(extradata) return event_args - def _prepare_form(self, entity, _rtype, role): - display_label = False - related_entity = entity - return display_label, related_entity - - def _prepare_composite_form(self, entity, rtype, role, edit_related, add_related): - display_label = True - if edit_related and not add_related: - related_entity = entity.related(rtype, role).get_entity(0, 0) - elif add_related: - _new_entity = self._cw.vreg['etypes'].etype_class(add_related)(self._cw) + def _prepare_form(self, entity, rschema, role, action): + assert action in ('edit_rtype', 'edit_related', 'add', 'delete'), action + if action == 'edit_rtype': + return False, entity + label = True + if action in ('edit_related', 'delete'): + edit_entity = entity.related(rschema, role).get_entity(0, 0) + elif action == 'add': + add_etype = self._compute_ttypes(rschema, role)[0] + _new_entity = self._cw.vreg['etypes'].etype_class(add_etype)(self._cw) _new_entity.eid = self._cw.varmaker.next() - related_entity = _new_entity + edit_entity = _new_entity # XXX see forms.py ~ 276 and entities.linked_to method # is there another way ? - self._cw.form['__linkto'] = '%s:%s:%s' % (rtype, entity.eid, neg_role(role)) - return display_label, related_entity + self._cw.form['__linkto'] = '%s:%s:%s' % (rschema, entity.eid, neg_role(role)) + assert edit_entity + return label, edit_entity def _build_renderer(self, related_entity, display_label): return self._cw.vreg['formrenderers'].select( @@ -266,13 +265,18 @@ display_help=False, button_bar_class='buttonbar', display_progress_div=False) - def _build_form(self, entity, rtype, role, divid, formid, reload, - display_label, related_entity, extradata=None, **formargs): - event_args = self._build_args(entity, rtype, role, formid, - reload, extradata) + def _build_form(self, entity, rschema, role, divid, formid, reload, action, + extradata=None, **formargs): + rtype = rschema.type + event_args = self._build_args(entity, rtype, role, formid, reload, action, extradata) + if not action: + form = _DummyForm() + form.event_args = event_args + return form, None + label, edit_entity = self._prepare_form(entity, rschema, role, action) cancelclick = self._cancelclick % divid form = self._cw.vreg['forms'].select( - formid, self._cw, rset=related_entity.as_rset(), entity=related_entity, + formid, self._cw, rset=edit_entity.as_rset(), entity=edit_entity, domid='%s-form' % divid, formtype='inlined', action=self._cw.build_url('validateform', __onsuccess='window.parent.cw.reledit.onSuccess'), cwtarget='eformframe', cssclass='releditForm', @@ -298,9 +302,10 @@ if formid == 'base': field = form.field_by_name(rtype, role, entity.e_schema) form.append_field(field) - return form, self._build_renderer(related_entity, display_label) + return form, self._build_renderer(edit_entity, label) - def _should_edit_attribute(self, entity, rschema): + def _should_edit_attribute(self, rschema): + entity = self.entity rdef = entity.e_schema.rdef(rschema) # check permissions if not entity.cw_has_perm('update'): @@ -312,8 +317,8 @@ ' use _should_edit_attribute instead', _should_edit_attribute) - def _should_edit_relation(self, entity, rschema, role): - eeid = entity.eid + def _should_edit_relation(self, rschema, role): + eeid = self.entity.eid perm_args = {'fromeid': eeid} if role == 'subject' else {'toeid': eeid} return rschema.has_perm(self._cw, 'add', **perm_args) @@ -335,9 +340,11 @@ w(u'