# HG changeset patch # User Sylvain Thénault <sylvain.thenault@logilab.fr> # Date 1276182103 -7200 # Thu Jun 10 17:01:43 2010 +0200 # Node ID c6e6d5adc287a3996fa5fd47e5bc88ba29c6257d # Parent d32c5dffe4b182fd15f3f267aeb67383f15b1514 use standard form validation instead of custom json controller's methods, support to apply the commment section component on entity not yet created (will be created with the comment) diff --git a/__pkginfo__.py b/__pkginfo__.py --- a/__pkginfo__.py +++ b/__pkginfo__.py @@ -23,7 +23,7 @@ 'Programming Language :: JavaScript', ] -__depends__ = {'cubicweb': '>= 3.6.0'} +__depends__ = {'cubicweb': '>= 3.9.0'} # package ### diff --git a/data/cubes.comment.js b/data/cubes.comment.js --- a/data/cubes.comment.js +++ b/data/cubes.comment.js @@ -4,58 +4,40 @@ * :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr */ -CubicWeb.require('python.js'); -CubicWeb.require('htmlhelpers.js'); -CubicWeb.require('ajax.js'); - -function _getText(textarea) { - if (typeof(FCKeditor) != 'undefined') { - var fck = FCKeditorAPI.GetInstance(textarea.id); - if (fck) { - return fck.GetHTML(); - } - } - return textarea.value; -} - /* this function is called on inlined-comment editions * It calls the [add|eid]_comment method on the jsoncontroller and [re]load * only the view for the added or edited comment */ -function processComment(eid, funcname, creation) { +function processComment(eid, cancel, creation) { var divId = 'comment' + eid + 'Slot' var divNode = jQuery('#'+divId); var textarea = divNode.find('textarea')[0]; - if (funcname) { - var format = 'text/html'; // no select widget if fckeditor is used - var select = divNode.find('select')[0]; - if (select) { - format = firstSelected(select); - } - d = asyncRemoteExec(funcname, eid, _getText(textarea), format); - d.addCallback(function (neweid) { - if (creation) { - var commentNode = jQuery('#comment'+ eid); - var ul = null; - if (!commentNode.length) { - // we are adding a comment to the top level entity - commentNode = jQuery('#commentsectionComponent'); - klass = 'comment'; - } else { - klass = 'section'; - } - ul = commentNode.find('> ul:first'); - if (!ul.length) { - ul = jQuery(UL({'class': klass})); - commentNode.append(ul); - } - ul.append(LI({'id': 'comment'+ neweid, 'class': 'comment'}, - DIV({'id': 'comment'+ neweid + 'Div'}))); - divNode.remove(); - eid = neweid; - } - replacePageChunk('comment' + eid + 'Div', rql_for_eid(eid), 'treeitem'); - }); + if (!cancel) { + validateForm('commentForm' + eid, null, + function(result, formid, cbargs) { + var neweid = result[2].eid; + if (creation) { + var commentNode = $('#comment'+ eid); + var ul = null; + if (!commentNode.length) { + // we are adding a comment to the top level entity + commentNode = $('#commentsectionComponent'); + klass = 'comment'; + } else { + klass = 'section'; + } + ul = commentNode.find('> ul:first'); + if (!ul.length) { + ul = jQuery(UL({'class': klass})); + commentNode.append(ul); + } + ul.append(LI({'id': 'comment'+ neweid, 'class': 'comment'}, + DIV({'id': 'comment'+ neweid + 'Div'}))); + divNode.remove(); + } + var form = ajaxFuncArgs('render', null, 'views', 'treeitem', neweid); + $('#comment' + neweid + 'Div').loadxhtml('json', form, null, null, true); + }); } else { // comment cancelled, close div holding the form divNode.remove(); @@ -71,6 +53,3 @@ $('html, body').animate({scrollTop:0}, 'fast'); return false; } - -CubicWeb.provide('comment.js'); - diff --git a/debian/control b/debian/control --- a/debian/control +++ b/debian/control @@ -10,7 +10,7 @@ Package: cubicweb-comment Architecture: all -Depends: cubicweb-common (>= 3.6.0) +Depends: cubicweb-common (>= 3.9.0) Description: comment component for the CubicWeb framework This CubicWeb component provides threadable comments. . diff --git a/test/unittest_comment.py b/test/unittest_comment.py --- a/test/unittest_comment.py +++ b/test/unittest_comment.py @@ -139,26 +139,6 @@ ''') -class CommentJsonControllerExtensionsTC(CubicWebTC): - - def setup_database(self): - self.john = self.create_user(u'John') - - def test_add_and_edit_comment(self): - # add comment - self.remote_call('add_comment', self.john.eid, u'yo', u'text/plain') - comment = self.entity('Any C,CT,F WHERE C content CT, C content_format F, ' - 'C comments P, P eid %s' % self.john.eid) - self.assertEquals(comment.content, u'yo') - self.assertEquals(comment.content_format, u'text/plain') - # edit comment - self.remote_call('edit_comment', comment.eid, u'yipee', u'text/plain') - comment2 = self.entity('Any C,CT,F WHERE C content CT, C content_format F, ' - 'C comments P, P eid %s' % self.john.eid) - self.assertEquals(comment.eid, comment2.eid) - self.assertEquals(comment2.content, u'yipee') - self.assertEquals(comment2.content_format, u'text/plain') - if __name__ == '__main__': from logilab.common.testlib import unittest_main diff --git a/views.py b/views.py --- a/views.py +++ b/views.py @@ -15,7 +15,9 @@ from cubicweb.web import dumps from cubicweb.selectors import (implements, has_permission, authenticated_user, - score_entity, relation_possible, one_line_rset) + score_entity, relation_possible, one_line_rset, + match_kwargs, match_form_params, + partial_relation_possible, traced_selection) from cubicweb.view import EntityView from cubicweb.uilib import rql_for_eid, cut, safe_cut from cubicweb.mixins import TreeViewMixIn @@ -193,15 +195,14 @@ # comment forms ################################################################ -class InlineEditCommentForm(form.FormViewMixIn, EntityView): +class InlineEditCommentFormView(form.FormViewMixIn, EntityView): __regid__ = 'editcommentform' __select__ = implements('Comment') - jsfunc = "processComment(%s, '%s', false)" - jsonmeth = 'edit_comment' + jsfunc = "processComment(%s, %s, false)" - def cell_call(self, row, col): - self.comment_form(self.cw_rset.get_entity(row, col)) + def entity_call(self, entity): + self.comment_form(entity) def propose_to_login(self): self.w(u'<div class="warning">%s ' % self._cw._('You are not authenticated.')) @@ -212,7 +213,7 @@ self.w(u'</div>') def comment_form(self, commented, newcomment=None): - self._cw.add_js('cubes.comment.js') + self._cw.add_js(('cubicweb.edition.js', 'cubes.comment.js')) if newcomment is None: newcomment = commented if self._cw.cnx.anonymous_connection: @@ -220,28 +221,53 @@ # hack to avoid tabindex conflicts caused by Ajax requests self._cw.next_tabindex = count(20).next jseid = dumps(commented.eid) - cancel_action = self.jsfunc % (jseid, '') - buttons = [fw.Button(onclick=self.jsfunc % (jseid, self.jsonmeth)), + buttons = [fw.Button(onclick=self.jsfunc % (jseid, 'false')), fw.Button(stdmsgs.BUTTON_CANCEL, - onclick=cancel_action)] - form = self._cw.vreg['forms'].select('edition', self._cw, - entity=newcomment, - form_buttons=buttons) + onclick=self.jsfunc % (jseid, 'true'))] + fvreg = self._cw.vreg['forms'] + if newcomment is not None and not commented.has_eid(): + form = fvreg.select('composite', self._cw, form_buttons=buttons, + domid='commentForm%s' % commented.eid, + form_renderer_id='default') + form.add_subform(fvreg.select('edition', self._cw, entity=commented, + mainform=False)) + cform = fvreg.select('edition', self._cw, entity=newcomment, + mainform=False) + form.add_subform(cform) + else: + form = fvreg.select('edition', self._cw, entity=newcomment, + domid='commentForm%s' % commented.eid, + form_buttons=buttons) + cform = form + if newcomment is not None: + cform.append_field(cform.field_by_name('comments', 'subject', + eschema=newcomment.e_schema)) + formvalues = {'comments': commented.eid} + else: + formvalues = {} self.w(u'<div id="comment%sSlot">%s</div>' % ( - commented.eid, form.render(main_form_title=u'', + commented.eid, form.render(formvalues={'comments': commented.eid}, + main_form_title=u'', display_label=False, display_relations_form=False))) -class InlineAddCommentForm(InlineEditCommentForm): +class InlineAddCommentFormView(InlineEditCommentFormView): __regid__ = 'addcommentform' - __select__ = relation_possible('comments', 'object', 'Comment', 'add') + __select__ = (relation_possible('comments', 'object', 'Comment', 'add') + | match_form_params('etype')) + + jsfunc = "processComment(%s, %s, true)" - jsfunc = "processComment(%s, '%s', true)" - jsonmeth = 'add_comment' + def call(self, **kwargs): + if self.cw_rset is None: + entity = self._cw.vreg['etypes'].etype_class(self._cw.form['etype'])(self._cw) + entity.eid = self._cw.varmaker.next() + self.entity_call(entity) + else: + super(InlineAddCommentFormView, self).call(**kwargs) - def cell_call(self, row, col): - commented = self.cw_rset.get_entity(row, col) + def entity_call(self, commented): newcomment = self._cw.vreg['etypes'].etype_class('Comment')(self._cw) newcomment.eid = self._cw.varmaker.next() self.comment_form(commented, newcomment) @@ -254,40 +280,42 @@ related to an object """ __regid__ = 'commentsection' - __select__ = (component.EntityVComponent.__select__ + __select__ = ((component.EntityVComponent.__select__ | match_kwargs('entity')) & relation_possible('comments', 'object', 'Comment')) context = 'navcontentbottom' - def cell_call(self, row, col, view=None): + def entity_call(self, entity, view=None): req = self._cw req.add_js( ('cubicweb.ajax.js', 'cubes.comment.js') ) - eid = self.cw_rset[row][col] + eid = entity.eid self.w(u'<div id="%s" class="%s" cubicweb:rooteid="%s">' % ( self.div_id(), self.div_class(), eid)) - rql = u'Any C,CD,CC,CCF,U,UL,US,UF ORDERBY CD WHERE C is Comment, '\ - 'C comments X, C creation_date CD, C content CC, C content_format CCF, ' \ - 'C created_by U?, U login UL, U firstname UF, U surname US, X eid %(x)s' - rset = req.execute(rql, {'x': eid}, 'x') - if rset.rowcount: - self.w(u'<h4>%s</h4>' % (req._('Comment_plural'))) - if rset.rowcount: - self.w(u'<ul class="comment">') - for i in xrange(rset.rowcount): - self.wview('tree', rset, row=i) - self.w(u'</ul>') + if entity.has_eid(): + rql = u'Any C,CD,CC,CCF,U,UL,US,UF ORDERBY CD WHERE C is Comment, '\ + 'C comments X, C creation_date CD, C content CC, C content_format CCF, ' \ + 'C created_by U?, U login UL, U firstname UF, U surname US, X eid %(x)s' + rset = req.execute(rql, {'x': eid}) + if rset.rowcount: + self.w(u'<h4>%s</h4>' % (req._('Comment_plural'))) + self.w(u'<ul class="comment">') + for i in xrange(rset.rowcount): + self.wview('tree', rset, row=i) + self.w(u'</ul>') self.w(u'</div>') - addcomment = self._cw.vreg['actions'].select_or_none('reply_comment', req, - rset=self.cw_rset, - row=row, col=col) + addcomment = self._cw.vreg['actions'].select_or_none( + 'reply_comment', req, entity=entity, + rset=entity.cw_rset, row=entity.cw_row, col=entity.cw_col) if addcomment is not None: self.w(u'<div id="comment%sHolder"></div>' % eid) - url = req.build_ajax_replace_url( - 'comment%sHolder' % eid, rql_for_eid(eid), 'addcommentform') + params = self.cw_extra_kwargs + if entity.has_eid(): + params['eid'] = eid + else: + params['etype'] = entity.__regid__ + url = req.ajax_replace_url( + 'comment%sHolder' % eid, vid='addcommentform', **params) self.w(u' (<a href="%s">%s</a>)' % (url, req._(addcomment.title))) - # XXX still necessary? - #if req.use_fckeditor() and req.property_value('ui.default-text-format') == 'text/html': - # req.fckeditor_config() class UserLatestCommentsSection(component.EntityVComponent): @@ -341,7 +369,9 @@ class AddCommentAction(LinkToEntityAction): """add comment is like reply for everything but Comment""" __regid__ = 'reply_comment' - __select__ = LinkToEntityAction.__select__ & ~implements('Comment') + __select__ = ((LinkToEntityAction.__select__ + | (match_kwargs('entity') & partial_relation_possible(action='add', strict=True))) + & ~implements('Comment')) rtype = 'comments' role = 'object' @@ -374,20 +404,3 @@ def url(self): return self._cw.build_url(rql=self.cw_rset.printable_rql(), vid='deleteconf') - - -# JSONController extensions through monkey-patching ############################ - -@monkeypatch(basecontrollers.JSonController) -@basecontrollers.jsonize -def js_add_comment(self, commented, text, format): - return self._cw.execute('INSERT Comment C: C comments X, C content %(text)s, ' - 'C content_format %(format)s WHERE X eid %(x)s', - {'format' : format, 'text' : text, 'x' : commented}, 'x')[0][0] - -@monkeypatch(basecontrollers.JSonController) -@basecontrollers.jsonize -def js_edit_comment(self, comment, text, format): - self._cw.execute('SET C content %(text)s, C content_format %(format)s ' - 'WHERE C eid %(x)s', - {'format' : format, 'text' : text, 'x' : comment}, 'x')