# HG changeset patch # User Sylvain Thénault # Date 1284735297 -7200 # Node ID c827fa795a6b9449eb0df8b95f65492ad68d0713 # Parent 556b1b1a2c5a0fddd1fefc1521c0bed7666fcfc9 [reledit] more api cleanup * deprecates usage of giving rvid/default_value to select (use rtag instead) * deprecates usage of _one_rvid/_many_rvid, use autolimited view instead diff -r 556b1b1a2c5a -r c827fa795a6b web/data/cubicweb.reledit.js --- a/web/data/cubicweb.reledit.js Fri Sep 17 16:54:56 2010 +0200 +++ b/web/data/cubicweb.reledit.js Fri Sep 17 16:54:57 2010 +0200 @@ -63,11 +63,11 @@ * @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, default_value) { + loadInlineEditionForm: function(formid, eid, rtype, role, divid, reload, vid) { var args = {fname: 'reledit_form', rtype: rtype, role: role, pageid: pageid, eid: eid, divid: divid, formid: formid, - reload: reload, vid: vid, default_value: default_value, + reload: reload, vid: vid, callback: function () {cw.reledit.showInlineEditionForm(divid);}}; jQuery('#'+divid+'-reledit').parent().loadxhtml(JSON_BASE_URL, args, 'post'); } diff -r 556b1b1a2c5a -r c827fa795a6b web/test/unittest_reledit.py --- a/web/test/unittest_reledit.py Fri Sep 17 16:54:56 2010 +0200 +++ b/web/test/unittest_reledit.py Fri Sep 17 16:54:57 2010 +0200 @@ -33,73 +33,71 @@ class ClickAndEditFormTC(ReleditMixinTC, CubicWebTC): def test_default_config(self): - reledit = {'title': """
cubicweb-world-domination
""", - 'long_desc': """
<long_desc not specified>
""", - 'manager': """
<manager not specified>
""", - 'composite_card11_2ttypes': """<composite_card11_2ttypes not specified>""", - 'concerns': """<concerns_object not specified>"""} + reledit = {'title': """
cubicweb-world-domination
""", + 'long_desc': """
<not specified>
""", + 'manager': """
<not specified>
""", + 'composite_card11_2ttypes': """<not specified>""", + 'concerns': """<not specified>"""} for rschema, ttypes, role in self.proj.e_schema.relation_definitions(includefinal=True): if rschema not in reledit: continue rtype = rschema.type - self.assertTextEquals(reledit[rtype], self.proj.view('reledit', rtype=rtype, role=role), rtype) + self.assertTextEquals(reledit[rtype] % {'eid': self.proj.eid}, self.proj.view('reledit', rtype=rtype, role=role), rtype) def test_default_forms(self): - doreledit = {'title': """
cubicweb-world-domination
+ doreledit = {'title': """
cubicweb-world-domination
- - - - - - + + + + + - + - - + +
- +
- + - +
-
""", +
""", - 'long_desc': """
<long_desc not specified>
+ 'long_desc': """
<not specified>
- - + + - + - - + - + - +
@@ -125,62 +123,61 @@
- + - +
-
""", +
""", - 'manager': """
<manager not specified>
+ 'manager': """
<not specified>
- - - - - - + + + + + + - - + - + - - + +
- - +
- + - +
-
""", - 'composite_card11_2ttypes': """<composite_card11_2ttypes not specified>""", - 'concerns': """<concerns_object not specified>""" +
""", + 'composite_card11_2ttypes': """<not specified>""", + 'concerns': """<not specified>""" } for rschema, ttypes, role in self.proj.e_schema.relation_definitions(includefinal=True): if rschema not in doreledit: continue rtype = rschema.type - self.assertTextEquals(doreledit[rtype], + self.assertTextEquals(doreledit[rtype] % {'eid': self.proj.eid, 'toto': self.toto.eid}, self.proj.view('doreledit', rtype=rtype, role=role, formid='edition' if rtype == 'long_desc' else 'base'), rtype) @@ -195,10 +192,10 @@ def test_with_uicfg(self): old_rctl = reledit_ctrl._tagdefs.copy() reledit_ctrl.tag_attribute(('Project', 'title'), - {'default_value': '', 'reload': True}) + {'novalue_label': '<title is required>', 'reload': True}) reledit_ctrl.tag_subject_of(('Project', 'long_desc', '*'), {'reload': True, 'edit_target': 'rtype', - 'default_value': u'<long_desc is required>'}) + 'novalue_label': u'<long_desc is required>'}) reledit_ctrl.tag_subject_of(('Project', 'manager', '*'), {'edit_target': 'related'}) reledit_ctrl.tag_subject_of(('Project', 'composite_card11_2ttypes', '*'), @@ -206,17 +203,17 @@ reledit_ctrl.tag_object_of(('Ticket', 'concerns', 'Project'), {'edit_target': 'rtype'}) reledit = { - 'title': """<div id="title-subject-917-reledit" onmouseout="jQuery('#title-subject-917').addClass('hidden')" onmouseover="jQuery('#title-subject-917').removeClass('hidden')" class="releditField"><div id="title-subject-917-value" class="editableFieldValue">cubicweb-world-domination</div><div id="title-subject-917" class="editableField hidden"><div id="title-subject-917-update" class="editableField" onclick="cw.reledit.loadInlineEditionForm('base', 917, 'title', 'subject', 'title-subject-917', true, '', '<title is required>');" title="click to edit this field"><img title="click to edit this field" src="data/pen_icon.png" alt="click to edit this field"/></div></div></div>""", - 'long_desc': """<div id="long_desc-subject-917-reledit" onmouseout="jQuery('#long_desc-subject-917').addClass('hidden')" onmouseover="jQuery('#long_desc-subject-917').removeClass('hidden')" class="releditField"><div id="long_desc-subject-917-value" class="editableFieldValue"><long_desc is required></div><div id="long_desc-subject-917" class="editableField hidden"><div id="long_desc-subject-917-update" class="editableField" onclick="cw.reledit.loadInlineEditionForm('base', 917, 'long_desc', 'subject', 'long_desc-subject-917', true, 'incontext', '<long_desc is required>');" title="click to edit this field"><img title="click to edit this field" src="data/pen_icon.png" alt="click to edit this field"/></div></div></div>""", - 'manager': """<div id="manager-subject-917-reledit" onmouseout="jQuery('#manager-subject-917').addClass('hidden')" onmouseover="jQuery('#manager-subject-917').removeClass('hidden')" class="releditField"><div id="manager-subject-917-value" class="editableFieldValue"><a href="http://testing.fr/cubicweb/personne/919" title="">Toto</a></div><div id="manager-subject-917" class="editableField hidden"><div id="manager-subject-917-update" class="editableField" onclick="cw.reledit.loadInlineEditionForm('edition', 917, 'manager', 'subject', 'manager-subject-917', false, 'incontext', '&lt;manager not specified&gt;');" title="click to edit this field"><img title="click to edit this field" src="data/pen_icon.png" alt="click to edit this field"/></div><div id="manager-subject-917-delete" class="editableField" onclick="cw.reledit.loadInlineEditionForm('deleteconf', 917, 'manager', 'subject', 'manager-subject-917', false, 'incontext', '&lt;manager not specified&gt;');" title="click to delete this value"><img title="click to delete this value" src="data/cancel.png" alt="click to delete this value"/></div></div></div>""", - 'composite_card11_2ttypes': """<composite_card11_2ttypes not specified>""", - 'concerns': """<div id="concerns-object-917-reledit" onmouseout="jQuery('#concerns-object-917').addClass('hidden')" onmouseover="jQuery('#concerns-object-917').removeClass('hidden')" class="releditField"><div id="concerns-object-917-value" class="editableFieldValue"><a href="http://testing.fr/cubicweb/ticket/918" title="">write the code</a></div><div id="concerns-object-917" class="editableField hidden"><div id="concerns-object-917-update" class="editableField" onclick="cw.reledit.loadInlineEditionForm('base', 917, 'concerns', 'object', 'concerns-object-917', false, 'csv', '&lt;concerns_object not specified&gt;');" title="click to edit this field"><img title="click to edit this field" src="data/pen_icon.png" alt="click to edit this field"/></div></div></div>""" + 'title': """<div id="title-subject-%(eid)s-reledit" onmouseout="jQuery('#title-subject-%(eid)s').addClass('hidden')" onmouseover="jQuery('#title-subject-%(eid)s').removeClass('hidden')" class="releditField"><div id="title-subject-%(eid)s-value" class="editableFieldValue">cubicweb-world-domination</div><div id="title-subject-%(eid)s" class="editableField hidden"><div id="title-subject-%(eid)s-update" class="editableField" onclick="cw.reledit.loadInlineEditionForm('base', %(eid)s, 'title', 'subject', 'title-subject-%(eid)s', true, '');" title="click to edit this field"><img title="click to edit this field" src="data/pen_icon.png" alt="click to edit this field"/></div></div></div>""", + 'long_desc': """<div id="long_desc-subject-%(eid)s-reledit" onmouseout="jQuery('#long_desc-subject-%(eid)s').addClass('hidden')" onmouseover="jQuery('#long_desc-subject-%(eid)s').removeClass('hidden')" class="releditField"><div id="long_desc-subject-%(eid)s-value" class="editableFieldValue"><long_desc is required></div><div id="long_desc-subject-%(eid)s" class="editableField hidden"><div id="long_desc-subject-%(eid)s-update" class="editableField" onclick="cw.reledit.loadInlineEditionForm('base', %(eid)s, 'long_desc', 'subject', 'long_desc-subject-%(eid)s', true, 'autolimited');" title="click to edit this field"><img title="click to edit this field" src="data/pen_icon.png" alt="click to edit this field"/></div></div></div>""", + 'manager': """<div id="manager-subject-%(eid)s-reledit" onmouseout="jQuery('#manager-subject-%(eid)s').addClass('hidden')" onmouseover="jQuery('#manager-subject-%(eid)s').removeClass('hidden')" class="releditField"><div id="manager-subject-%(eid)s-value" class="editableFieldValue"><a href="http://testing.fr/cubicweb/personne/%(toto)s" title="">Toto</a></div><div id="manager-subject-%(eid)s" class="editableField hidden"><div id="manager-subject-%(eid)s-update" class="editableField" onclick="cw.reledit.loadInlineEditionForm('edition', %(eid)s, 'manager', 'subject', 'manager-subject-%(eid)s', false, 'autolimited');" title="click to edit this field"><img title="click to edit this field" src="data/pen_icon.png" alt="click to edit this field"/></div><div id="manager-subject-%(eid)s-delete" class="editableField" onclick="cw.reledit.loadInlineEditionForm('deleteconf', %(eid)s, 'manager', 'subject', 'manager-subject-%(eid)s', false, 'autolimited');" title="click to delete this value"><img title="click to delete this value" src="data/cancel.png" alt="click to delete this value"/></div></div></div>""", + 'composite_card11_2ttypes': """<not specified>""", + 'concerns': """<div id="concerns-object-%(eid)s-reledit" onmouseout="jQuery('#concerns-object-%(eid)s').addClass('hidden')" onmouseover="jQuery('#concerns-object-%(eid)s').removeClass('hidden')" class="releditField"><div id="concerns-object-%(eid)s-value" class="editableFieldValue"><a href="http://testing.fr/cubicweb/ticket/%(tick)s" title="">write the code</a></div><div id="concerns-object-%(eid)s" class="editableField hidden"><div id="concerns-object-%(eid)s-update" class="editableField" onclick="cw.reledit.loadInlineEditionForm('base', %(eid)s, 'concerns', 'object', 'concerns-object-%(eid)s', false, 'autolimited');" title="click to edit this field"><img title="click to edit this field" src="data/pen_icon.png" alt="click to edit this field"/></div></div></div>""" } for rschema, ttypes, role in self.proj.e_schema.relation_definitions(includefinal=True): if rschema not in reledit: continue rtype = rschema.type - self.assertTextEquals(reledit[rtype], + self.assertTextEquals(reledit[rtype] % {'eid': self.proj.eid, 'toto': self.toto.eid, 'tick': self.tick.eid}, self.proj.view('reledit', rtype=rtype, role=role), rtype) reledit_ctrl.clear() diff -r 556b1b1a2c5a -r c827fa795a6b web/uicfg.py --- a/web/uicfg.py Fri Sep 17 16:54:56 2010 +0200 +++ b/web/uicfg.py Fri Sep 17 16:54:57 2010 +0200 @@ -378,9 +378,9 @@ Possible keys and associated values are: - * `default_value`, alternative default value (shown when there is no value). + * `novalue_label`, alternative default value (shown when there is no value). - * `default_showlabel`, when `default_value` is not specified, this boolean + * `novalue_include_rtype`, when `novalue_label` is not specified, this boolean flag control wether the generated default value should contains the relation label or not. Will be the opposite of the `showlabel` value found in the `primaryview_display_ctrl` rtag by default. @@ -391,17 +391,15 @@ page. Defaults to False. * `rvid`, alternative view id (as str) for relation or composite edition. - Default is 'incontext' or 'csv' depending on the cardinality. They can - also be statically changed by subclassing :class:`ClickAndEditFormView` - and redefining `_one_rvid` (resp. `_many_rvid`). + Default is 'autolimited'. * `edit_target`, may be either 'rtype' (to edit the relation) or 'related' (to edit the related entity). This controls whether to edit the relation or the target entity of the relation. Currently only one-to-one relations support target entity edition. By default, the 'related' option is taken - whenever the relation is composite and one-to-one. + whenever the relation is composite. """ - _keys = frozenset('default_value default_showlabel reload rvid edit_target'.split()) + _keys = frozenset('novalue_label novalue_include_rtype reload rvid edit_target'.split()) def tag_relation(self, key, tag): for tagkey in tag.iterkeys(): @@ -426,11 +424,11 @@ edittarget = 'related' if composite else 'rtype' rtag.tag_relation((sschema, rschema, oschema, role), {'edit_target': edittarget}) - if not 'default_showlabel' in values: + if not 'novalue_include_rtype' in values: showlabel = primaryview_display_ctrl.get( sschema, rschema, oschema, role).get('showlabel', True) rtag.tag_relation((sschema, rschema, oschema, role), - {'default_showlabel': not showlabel}) + {'novalue_include_rtype': not showlabel}) reledit_ctrl = ReleditTags('reledit', init_reledit_ctrl) diff -r 556b1b1a2c5a -r c827fa795a6b web/views/basecontrollers.py --- a/web/views/basecontrollers.py Fri Sep 17 16:54:56 2010 +0200 +++ b/web/views/basecontrollers.py Fri Sep 17 16:54:57 2010 +0200 @@ -458,7 +458,7 @@ def js_reledit_form(self): req = self._cw args = dict((x, req.form[x]) - for x in ('formid', 'rtype', 'role', 'reload', 'default_value')) + for x in ('formid', 'rtype', 'role', 'reload')) rset = req.eid_rset(typed_eid(self._cw.form['eid'])) try: args['reload'] = json.loads(args['reload']) diff -r 556b1b1a2c5a -r c827fa795a6b web/views/primary.py --- a/web/views/primary.py Fri Sep 17 16:54:56 2010 +0200 +++ b/web/views/primary.py Fri Sep 17 16:54:57 2010 +0200 @@ -290,12 +290,15 @@ class RelatedView(EntityView): + """Display a rset, usually containing entities linked to another entity + being displayed. + + It will try to display nicely according to the number of items in the result + set. + """ __regid__ = 'autolimited' def call(self, **kwargs): - # nb: rset is retreived using entity.related with limit + 1 if any. - # Because of that, we know that rset.printable_rql() will return rql - # with no limit set anyway (since it's handled manually) if 'dispctrl' in self.cw_extra_kwargs: limit = self.cw_extra_kwargs['dispctrl'].get('limit') subvid = self.cw_extra_kwargs['dispctrl'].get('subvid', 'incontext') diff -r 556b1b1a2c5a -r c827fa795a6b web/views/reledit.py --- a/web/views/reledit.py Fri Sep 17 16:54:56 2010 +0200 +++ b/web/views/reledit.py Fri Sep 17 16:54:57 2010 +0200 @@ -19,6 +19,7 @@ """ import copy +from warnings import warn from logilab.mtconverter import xml_escape from logilab.common.deprecation import deprecated @@ -49,7 +50,7 @@ # ui side continuations _onclick = (u"cw.reledit.loadInlineEditionForm('%(formid)s', %(eid)s, '%(rtype)s', '%(role)s', " - "'%(divid)s', %(reload)s, '%(vid)s', '%(default_value)s');") + "'%(divid)s', %(reload)s, '%(vid)s');") _cancelclick = "cw.reledit.cleanupAfterCancel('%s')" # ui side actions/buttons @@ -60,10 +61,6 @@ _editzone = u'<img title="%(msg)s" src="data/pen_icon.png" alt="%(msg)s"/>' _editzonemsg = _('click to edit this field') - # default relation vids according to cardinality - # can be changed per rtype using reledit_ctrl rtag - _one_rvid = 'incontext' - _many_rvid = 'csv' # renderer _form_renderer_id = 'base' @@ -83,53 +80,53 @@ 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, '*') + 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) - default_value = self._compute_default_value(entity, rschema, role, default_value) divid = self._build_divid(rtype, role, entity.eid) if rschema.final: - self._handle_attribute(entity, rschema, role, divid, reload, default_value) + self._handle_attribute(entity, rschema, role, divid, reload) else: if self._is_composite(): - self._handle_composite(entity, rschema, role, divid, reload, default_value, formid) + self._handle_composite(entity, rschema, role, divid, reload, formid) else: - self._handle_relation(entity, rschema, role, divid, reload, default_value, formid) + self._handle_relation(entity, rschema, role, divid, reload, formid) - def _handle_attribute(self, entity, rschema, role, divid, reload, default_value): + 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): self.w(value) return - display_label, related_entity = self._prepare_form(entity, rtype, role) - form, renderer = self._build_form(entity, rtype, role, divid, 'base', default_value, + form, renderer = self._build_form(entity, rtype, role, divid, 'base', reload, display_label, related_entity) - value = value or default_value + value = value or self._compute_default_value(rschema, role) self.view_form(divid, value, form, renderer) - def _compute_formid_value(self, entity, rschema, role, default_value, rvid, formid): + def _compute_formid_value(self, entity, rschema, role, rvid, formid): related_rset = entity.related(rschema.type, role) if related_rset: value = self._cw.view(rvid, related_rset) else: - value = default_value + value = self._compute_default_value(rschema, role) if not self._should_edit_relation(entity, rschema, role): return None, value return formid, value - def _handle_relation(self, entity, rschema, role, divid, reload, default_value, formid): + def _handle_relation(self, entity, rschema, role, divid, reload, formid): rvid = self._compute_best_vid(entity.e_schema, rschema, role) - formid, value = self._compute_formid_value(entity, rschema, role, default_value, rvid, formid) + formid, value = self._compute_formid_value(entity, 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, default_value, reload, + form, renderer = self._build_form(entity, rtype, role, divid, formid, reload, display_label, related_entity, dict(vid=rvid)) self.view_form(divid, value, form, renderer) - def _handle_composite(self, entity, rschema, role, divid, reload, default_value, formid): + def _handle_composite(self, entity, rschema, role, divid, reload, formid): # this is for attribute-like composites (1 target type, 1 related entity at most, for now) ttypes = self._compute_ttypes(rschema, role) related_rset = entity.related(rschema.type, role) @@ -138,7 +135,7 @@ delete_related = edit_related and self._may_delete_related(related_rset, entity, rschema, role) rvid = self._compute_best_vid(entity.e_schema, rschema, role) - formid, value = self._compute_formid_value(entity, rschema, role, default_value, rvid, formid) + formid, value = self._compute_formid_value(entity, 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) @@ -148,16 +145,28 @@ 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, default_value, reload, + form, renderer = self._build_form(entity, rtype, role, divid, formid, reload, display_label, related_entity, dict(vid=rvid)) self.view_form(divid, value, form, renderer, edit_related, add_related, delete_related) def _compute_best_vid(self, eschema, rschema, role): - rvid = self._one_rvid - if eschema.rdef(rschema, role).role_cardinality(role) in '+*': - rvid = self._many_rvid - return self._rules.get('rvid', rvid) + vid = self._rules.get('rvid', None) + if vid is None: + try: + if eschema.rdef(rschema, role).role_cardinality(role) in '+*': + vid = self._many_rvid + warn('[3.9] %s overriding _one_rvid is deprecated, use ' + 'reledit_ctrl rtag to control this' % self, DeprecationWarning) + else: + vid = self._one_rvid + warn('[3.9] %s overriding _many_rvid is deprecated, use ' + 'reledit_ctrl rtag to control this' % self, DeprecationWarning) + except AttributeError: + pass + if vid is None: + vid = 'autolimited' + return vid def _compute_ttypes(self, rschema, role): dual_role = neg_role(role) @@ -171,17 +180,15 @@ ctrl_reload = self._cw.build_url(ctrl_reload) return ctrl_reload - def _compute_default_value(self, entity, rschema, role, default_value): - etype = entity.e_schema.type - ctrl_default = self._rules.get('default_value', default_value) - if ctrl_default: - return ctrl_default - if default_value is None: - if self._rules.get('default_showlabel'): - return xml_escape(self._cw._('<%s not specified>') % - display_name(self._cw, rschema.type, role)) - return xml_escape(self._cw._('<not specified>')) - return default_value + def _compute_default_value(self, rschema, role): + default = self._rules.get('novalue_label') + if default is None: + if self._rules.get('novalue_include_rtype'): + default = self._cw._('<%s not specified>') % display_name( + self._cw, rschema.type, role) + else: + default = self._cw._('<not specified>') + return xml_escape(default) def _is_composite(self): return self._rules.get('edit_target') == 'related' @@ -233,11 +240,11 @@ """ 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, default_value, reload, + def _build_args(self, entity, rtype, role, formid, reload, 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), 'default_value' : default_value, + 'reload' : json_dumps(reload), 'role' : role, 'vid' : u''} if extradata: event_args.update(extradata) @@ -269,9 +276,9 @@ display_help=False, button_bar_class='buttonbar', display_progress_div=False) - def _build_form(self, entity, rtype, role, divid, formid, default_value, reload, + 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, default_value, + event_args = self._build_args(entity, rtype, role, formid, reload, extradata) cancelclick = self._cancelclick % divid form = self._cw.vreg['forms'].select( @@ -382,9 +389,9 @@ class AutoClickAndEditFormView(ClickAndEditFormView): __regid__ = 'reledit' - def _build_form(self, entity, rtype, role, divid, formid, default_value, reload, + 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, 'base', default_value, + event_args = self._build_args(entity, rtype, role, 'base', reload, extradata) form = _DummyForm() form.event_args = event_args