# HG changeset patch
# User Sylvain Thénault <sylvain.thenault@logilab.fr>
# Date 1272026481 -7200
#      Fri Apr 23 14:41:21 2010 +0200
# Branch stable
# Node ID 6c9687eb82ba140e29cd41207cfd999c837d3643
# Parent  e96428b232ebc70545146719483faa8f5edd32ef
properly fix #79178: Link to Latest comments of a user by using a contextual component

also refactor comment oneline view on the way

diff --git a/i18n/en.po b/i18n/en.po
--- a/i18n/en.po
+++ b/i18n/en.po
@@ -24,6 +24,9 @@
 msgid "Comment_plural"
 msgstr "Comments"
 
+msgid "Latest comments"
+msgstr ""
+
 msgid "New Comment"
 msgstr "New comment"
 
@@ -67,6 +70,9 @@
 msgid "add comment"
 msgstr ""
 
+msgid "comment content"
+msgstr "comment"
+
 # #-#-#-#-#  schema.pot  #-#-#-#-#
 # subject and object forms for each relation type
 # (no object form for final relation types)
@@ -106,6 +112,12 @@
 "section containing comments thread an allowing to post comment on "
 "commentable entities"
 
+msgid "contentnavigation_latestcomments"
+msgstr ""
+
+msgid "contentnavigation_latestcomments_description"
+msgstr ""
+
 msgid "delete comment"
 msgstr ""
 
@@ -115,15 +127,15 @@
 msgid "i18n_by_author_field"
 msgstr "by"
 
-msgid "latest comment(s):"
-msgstr ""
-
 msgid "login"
 msgstr ""
 
 msgid "new comment for"
 msgstr ""
 
+msgid "on date"
+msgstr "date"
+
 msgid "register"
 msgstr ""
 
diff --git a/i18n/fr.po b/i18n/fr.po
--- a/i18n/fr.po
+++ b/i18n/fr.po
@@ -24,6 +24,9 @@
 msgid "Comment_plural"
 msgstr "Commentaires"
 
+msgid "Latest comments"
+msgstr "Derniers commentaires"
+
 msgid "New Comment"
 msgstr "Nouveau commentaire"
 
@@ -68,6 +71,9 @@
 msgid "add comment"
 msgstr "ajouter un commentaire"
 
+msgid "comment content"
+msgstr "commentaire"
+
 # #-#-#-#-#  schema.pot  #-#-#-#-#
 # subject and object forms for each relation type
 # (no object form for final relation types)
@@ -104,7 +110,14 @@
 
 msgid "contentnavigation_commentsection_description"
 msgstr ""
-"partie affichant la liste des commentaires à propos de l'entité visualisée"
+"section affichant la liste des commentaires à propos de l'entité visualisée"
+
+msgid "contentnavigation_latestcomments"
+msgstr "derniers commentaires de l'utilisateur"
+
+msgid "contentnavigation_latestcomments_description"
+msgstr ""
+"section affichant la liste des dernierscommentaires postés par un utilisateur"
 
 msgid "delete comment"
 msgstr "supprimer ce commentaire"
@@ -115,15 +128,15 @@
 msgid "i18n_by_author_field"
 msgstr "par"
 
-msgid "latest comment(s):"
-msgstr "derniers commentaire(s) :"
-
 msgid "login"
 msgstr "s'authentifier"
 
 msgid "new comment for"
 msgstr "nouveau commentaire pour"
 
+msgid "on date"
+msgstr "date"
+
 msgid "register"
 msgstr "s'enregistrer"
 
@@ -142,6 +155,3 @@
 
 msgid "written by"
 msgstr "écrit par"
-
-#~ msgid "to comment"
-#~ msgstr "pour commenter"
diff --git a/schema.py b/schema.py
--- a/schema.py
+++ b/schema.py
@@ -3,11 +3,7 @@
 :copyright: 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
 """
-from yams.buildobjs import EntityType, RelationType, SubjectRelation
-try:
-    from yams.buildobjs import RichString
-except:
-    from cubicweb.schema import RichString
+from yams.buildobjs import EntityType, RelationType, SubjectRelation, RichString
 from cubicweb.schema import RRQLExpression
 
 class Comment(EntityType):
diff --git a/views.py b/views.py
--- a/views.py
+++ b/views.py
@@ -14,34 +14,26 @@
 
 from simplejson import dumps
 
-from cubicweb.selectors import (one_line_rset, implements,
-                                has_permission, relation_possible, yes,
-                                match_kwargs, score_entity,
-                                authenticated_user)
+from cubicweb.selectors import (implements, has_permission, authenticated_user,
+                                score_entity, relation_possible, one_line_rset)
 from cubicweb.view import EntityView
 from cubicweb.uilib import rql_for_eid, cut, safe_cut
 from cubicweb.mixins import TreeViewMixIn
-from cubicweb.web import stdmsgs, uicfg
+from cubicweb.web import stdmsgs, uicfg, component, form, formwidgets as fw
 from cubicweb.web.action import LinkToEntityAction, Action
-from cubicweb.web.form import FormViewMixIn
-from cubicweb.web.formwidgets import Button
-from cubicweb.web.views import primary, baseviews, xmlrss
-from cubicweb.web.component import EntityVComponent
-from cubicweb.web.views.basecontrollers import JSonController, jsonize
+from cubicweb.web.views import primary, baseviews, xmlrss, basecontrollers
 
+_afs = uicfg.autoform_section
+_afs.tag_subject_of(('*', 'comments', '*'), formtype='main', section='hidden')
+_afs.tag_object_of(('*', 'comments', '*'), formtype='main', section='hidden')
 
-uicfg.autoform_section.tag_subject_of(('*', 'comments', '*'), formtype='main', section='hidden')
-uicfg.autoform_section.tag_object_of(('*', 'comments', '*'), formtype='main', section='hidden')
-uicfg.actionbox_appearsin_addmenu.tag_subject_of(('*', 'comments', '*'),  False)
-uicfg.actionbox_appearsin_addmenu.tag_object_of(('*', 'comments', '*'), False)
-uicfg.primaryview_section.tag_subject_of(('*', 'comments', '*'),  'hidden')
-uicfg.primaryview_section.tag_object_of(('*', 'comments', '*'), 'hidden')
-# XXX this is probably *very* inefficient since we'll fetch all entities created by the user
-uicfg.primaryview_section.tag_object_of(('*', 'created_by', 'CWUser'), 'relations')
-uicfg.primaryview_display_ctrl.tag_object_of(
-    ('*', 'created_by', 'CWUser'),
-    {'vid': 'list', 'label': _('latest comment(s):'), 'limit': True,
-     'filter': lambda rset: rset.filtered_rset(lambda x: x.e_schema == 'Comment')})
+_abaa = uicfg.actionbox_appearsin_addmenu
+_abaa.tag_subject_of(('*', 'comments', '*'),  False)
+_abaa.tag_object_of(('*', 'comments', '*'), False)
+
+_pvs = uicfg.primaryview_section
+_pvs.tag_subject_of(('*', 'comments', '*'),  'hidden')
+_pvs.tag_object_of(('*', 'comments', '*'), 'hidden')
 
 
 # comment views ###############################################################
@@ -80,21 +72,39 @@
         self.w(u'</div>\n')
 
 
+class CommentRootView(EntityView):
+    __regid__ = 'commentroot'
+    __select__ = implements('Comment')
+
+    def cell_call(self, row, col, **kwargs):
+        entity = self.cw_rset.get_entity(row, col)
+        root = entity.root()
+        self.w(u'<a href="%s">%s %s</a> ' % (
+            xml_escape(root.absolute_url()),
+            xml_escape(root.dc_type()),
+            xml_escape(cut(root.dc_title(), 40))))
+
+
+class CommentSummary(EntityView):
+    __regid__ = 'commentsummary'
+    __select__ = implements('Comment')
+
+    def cell_call(self, row, col, **kwargs):
+        entity = self.cw_rset.get_entity(row, col)
+        maxsize = self._cw.property_value('navigation.short-line-size')
+        content = entity.printable_value('content', format='text/plain')
+        self.w(xml_escape(cut(content, maxsize)))
+
 
 class CommentOneLineView(baseviews.OneLineView):
     __select__ = implements('Comment')
 
     def cell_call(self, row, col, **kwargs):
         entity = self.cw_rset.get_entity(row, col)
-        root = entity.root()
-        self.w(u'[<a href="%s">#%s</a>] '
-               % (xml_escape(root.absolute_url()), root.eid))
-        maxsize = self._cw.property_value('navigation.short-line-size')
-        maxsize = maxsize - len(str(root.eid))
-        content = entity.printable_value('content', format='text/plain')
-        content = xml_escape(cut(content, maxsize))
-        self.w(u'<a href="%s">#%s <i>%s</i></a>\n' % (
-            xml_escape(entity.absolute_url()), entity.eid, content))
+        self.w(u'[%s] ' % self.entity.view('commentroot'))
+        self.w(u'<a href="%s"><i>%s</i></a>\n' % (
+            xml_escape(entity.absolute_url()),
+            entity.view('commentsummary')))
 
 
 class CommentTreeItemView(baseviews.ListItemView):
@@ -161,9 +171,29 @@
         self.w(u'<li id="comment%s" class="comment">\n' % entity.eid)
 
 
-# comment edition views #######################################################
+class RssItemCommentView(xmlrss.RSSItemView):
+    __select__ = implements('Comment')
 
-class InlineEditCommentForm(FormViewMixIn, EntityView):
+    def cell_call(self, row, col):
+        entity = self.cw_rset.complete_entity(row, col)
+        self.w(u'<item>\n')
+        self.w(u'<guid isPermaLink="true">%s</guid>\n'
+               % xml_escape(entity.absolute_url()))
+        self.render_title_link(entity)
+        description = entity.dc_description(format='text/html') + \
+                      self._cw._(u'about') + \
+                      u' <a href=%s>%s</a>' % (entity.root().absolute_url(),
+                                               entity.root().dc_title())
+        self._marker('description', description)
+        self._marker('dc:date', entity.dc_date(self.date_format))
+        self.render_entity_creator(entity)
+        self.w(u'</item>\n')
+        self.wview('rssitem', entity.related('comments', 'object'), 'null')
+
+
+# comment forms ################################################################
+
+class InlineEditCommentForm(form.FormViewMixIn, EntityView):
     __regid__ = 'editcommentform'
     __select__ = implements('Comment')
 
@@ -191,9 +221,9 @@
         self._cw.next_tabindex = count(20).next
         jseid = dumps(commented.eid)
         cancel_action = self.jsfunc % (jseid, '')
-        buttons = [Button(onclick=self.jsfunc % (jseid, self.jsonmeth)),
-                   Button(stdmsgs.BUTTON_CANCEL,
-                          onclick=cancel_action)]
+        buttons = [fw.Button(onclick=self.jsfunc % (jseid, self.jsonmeth)),
+                   fw.Button(stdmsgs.BUTTON_CANCEL,
+                             onclick=cancel_action)]
         form = self._cw.vreg['forms'].select('edition', self._cw,
                                              entity=newcomment,
                                              form_buttons=buttons)
@@ -217,14 +247,14 @@
         self.comment_form(commented, newcomment)
 
 
-# comment component ###########################################################
+# contextual components ########################################################
 
-class CommentSectionVComponent(EntityVComponent):
+class CommentSectionVComponent(component.EntityVComponent):
     """a component to display a <div> html section including comments
     related to an object
     """
     __regid__ = 'commentsection'
-    __select__ = (EntityVComponent.__select__
+    __select__ = (component.EntityVComponent.__select__
                   & relation_possible('comments', 'object', 'Comment'))
 
     context = 'navcontentbottom'
@@ -260,7 +290,32 @@
             #    req.fckeditor_config()
 
 
-# comment actions #############################################################
+class UserLatestCommentsSection(component.EntityVComponent):
+    """a section to display latest comments by a user"""
+    __select__ = component.EntityVComponent.__select__ & implements('CWUser')
+    __regid__ = 'latestcomments'
+
+    def cell_call(self, row, col, view=None):
+        user = self.cw_rset.get_entity(row, col)
+        maxrelated = self._cw.property_value('navigation.related-limit') + 1
+        rset = self._cw.execute(
+            'Any C,CD,C,CCF ORDERBY CD DESC LIMIT %s WHERE C is Comment, '
+            'C creation_date CD, C content CC, C content_format CCF, '
+            'C created_by U, U eid %%(u)s' % maxrelated,
+            {'u': user.eid})
+        if rset:
+            self.w(u'<div class="section">')
+            self.w(u'<h4>%s</h4>\n' % self._cw._('Latest comments').capitalize())
+            self.wview('table', rset,
+                       headers=[_('about'), _('on date'),
+                                _('comment content')],
+                       cellvids={0: 'commentroot',
+                                 2: 'commentsummary',
+                                 })
+            self.w(u'</div>')
+
+
+# actions ######################################################################
 
 class ReplyCommentAction(LinkToEntityAction):
     __regid__ = 'reply_comment'
@@ -310,8 +365,7 @@
 
 class DeleteCommentAction(Action):
     __regid__ = 'delete_comment'
-    __select__ = implements('Comment') & \
-                 authenticated_user() & \
+    __select__ = implements('Comment') & authenticated_user() & \
                  score_entity(lambda x: not x.reverse_comments and x.has_perm('delete'))
 
     title = _('delete comment')
@@ -321,40 +375,19 @@
     def url(self):
         return self._cw.build_url(rql=self.cw_rset.printable_rql(), vid='deleteconf')
 
-# add some comments related methods to the Jsoncontroller #####################
+
+# JSONController extensions through monkey-patching ############################
 
-@monkeypatch(JSonController)
-@jsonize
+@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(JSonController)
-@jsonize
+@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')
-
-
-# RSS view ####################################################################
-
-class RssItemCommentView(xmlrss.RSSItemView):
-    __select__ = implements('Comment')
-
-    def cell_call(self, row, col):
-        entity = self.cw_rset.complete_entity(row, col)
-        self.w(u'<item>\n')
-        self.w(u'<guid isPermaLink="true">%s</guid>\n'
-               % xml_escape(entity.absolute_url()))
-        self.render_title_link(entity)
-        description = entity.dc_description(format='text/html') + \
-                      self._cw._(u'about') + \
-                      u' <a href=%s>%s</a>' % (entity.root().absolute_url(),
-                                               entity.root().dc_title())
-        self._marker('description', description)
-        self._marker('dc:date', entity.dc_date(self.date_format))
-        self.render_entity_creator(entity)
-        self.w(u'</item>\n')
-        self.wview('rssitem', entity.related('comments', 'object'), 'null')