Changeset 2787

Show
Ignore:
Timestamp:
11/16/07 04:00:08 (1 year ago)
Author:
osimons
Message:

FullBlogPlugin: Timeline support added

Timeline support is differentiating between 'Blog posts' (as first version with body), and 'Blog details' which is all updates (showing version comment instead of body), comments on posts and attachments. This makes version 1 the 'official' blog record, and works quite well as RSS feed.

Feedback on timeline / rss strategy is welcome.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • fullblogplugin/0.11/setup.py

    r2710 r2787  
    2525            'tracfullblog.db = tracfullblog.db', 
    2626            'tracfullblog.web_ui = tracfullblog.web_ui']}, 
    27       package_data={'tracfullblog' : ['htdocs/css/*.css','htdocs/js/*.js', 'templates/*.html', ]}, 
     27      package_data={'tracfullblog' : ['htdocs/*.png', 
     28                                      'htdocs/css/*.css', 
     29                                      'htdocs/js/*.js', 
     30                                      'templates/*.html', ]}, 
    2831      install_requires = []) 
  • fullblogplugin/0.11/tracfullblog/core.py

    r2783 r2787  
    8787        bp = BlogPost(self.env, resource.id, resource.version) 
    8888        if context: 
    89             return tag.a(bp.title, href=context.href.blog(resource.id)) 
     89            return tag.a('Blog: '+bp.title, href=context.href.blog(resource.id)) 
    9090        else: 
    91             return bp.title 
     91            return 'Blog: '+bp.title 
    9292 
    9393    # IWikiSyntaxProvider methods 
  • fullblogplugin/0.11/tracfullblog/htdocs/css/fullblog.css

    r2784 r2787  
     1/* 
     2** Styles for the /blog pages 
     3*/  
     4 
    15.blog #main { 
    26    width: 75%; 
     
    6064    border-bottom: none; 
    6165} 
     66 
     67/* 
     68** Style used for displaying Blog icon in Timeline 
     69*/  
     70 
     71.timeline dt.blog { 
     72    background-image: url(../blog.png); 
     73} 
  • fullblogplugin/0.11/tracfullblog/web_ui.py

    r2779 r2787  
    1313import re 
    1414from pkg_resources import resource_filename 
     15from operator import itemgetter 
    1516 
    1617# Trac and Genshi imports 
     
    1920from trac.core import * 
    2021from trac.mimeview.api import Context 
     22from trac.resource import Resource 
    2123from trac.search.api import ISearchSource, shorten_result 
     24from trac.timeline.api import ITimelineEventProvider 
     25from trac.util.compat import sorted 
    2226from trac.util.datefmt import to_datetime, to_unicode, localtz 
    2327from trac.util.translation import _ 
     
    2529from trac.web.chrome import INavigationContributor, ITemplateProvider, \ 
    2630                            add_stylesheet 
     31from trac.wiki.formatter import format_to_oneliner, format_to_html 
    2732 
    2833# Imports from same package 
     
    4550     
    4651    implements(IRequestHandler, INavigationContributor, 
    47                ISearchSource, ITemplateProvider) 
     52               ISearchSource, ITimelineEventProvider, 
     53               ITemplateProvider) 
    4854 
    4955    # INavigationContributor methods 
     
    295301                    shorten_result(text=comment, keywords=terms)) 
    296302     
     303    # ITimelineEventProvider methods 
     304 
     305    def get_timeline_filters(self, req): 
     306        if 'BLOG_VIEW' in req.perm: 
     307            yield ('blog', _('Blog posts')) 
     308            yield ('blog-details', _('Blog details')) 
     309 
     310    def get_timeline_events(self, req, start, stop, filters): 
     311        if 'blog' in filters or 'blog-details' in filters: 
     312            add_stylesheet(req, 'tracfullblog/css/fullblog.css') 
     313            blog_realm = Resource('blog') 
     314            blog_posts = get_blog_posts(self.env, from_dt=start, to_dt=stop, 
     315                                        all_versions=True) 
     316        if 'blog' in filters: 
     317            # Blog posts 
     318            for name, version, time, author, title, body, category_list \ 
     319                    in blog_posts: 
     320                bp_resource = blog_realm(id=name, version=version) 
     321                if 'BLOG_VIEW' not in req.perm(bp_resource): 
     322                    continue 
     323                if version != 1: 
     324                    continue # Only interested in first version here 
     325                bp = BlogPost(self.env, name, version=version) 
     326                yield ('blog', bp.version_time, bp.version_author, 
     327                            (bp_resource, bp, None)) 
     328        if 'blog-details' in filters: 
     329            # Blog posts 
     330            for name, version, time, author, title, body, category_list \ 
     331                    in blog_posts: 
     332                bp_resource = blog_realm(id=name, version=version) 
     333                if 'BLOG_VIEW' not in req.perm(bp_resource): 
     334                    continue 
     335                if version == 1 and 'blog' in filters: 
     336                    continue # First version handled above 
     337                bp = BlogPost(self.env, name, version=version) 
     338                yield ('blog', bp.version_time, bp.version_author, 
     339                            (bp_resource, bp, None)) 
     340            # Attachments (will be rendered by attachment module) 
     341            for event in AttachmentModule(self.env).get_timeline_events( 
     342                req, blog_realm, start, stop): 
     343                yield event 
     344            # Blog comments 
     345            blog_comments = get_blog_comments(self.env, from_dt=start, to_dt=stop) 
     346            blog_comments = sorted(blog_comments, key=itemgetter(4), reverse=True) 
     347            for post_name, number, comment, author, time in blog_comments: 
     348                bp_resource = blog_realm(id=post_name) 
     349                if 'BLOG_VIEW' not in req.perm(bp): 
     350                    continue 
     351                bp = BlogPost(self.env, post_name) 
     352                bc = BlogComment(self.env, post_name, number=number) 
     353                yield ('blog', time, author, (bp_resource, bp, bc)) 
     354 
     355 
     356    def render_timeline_event(self, context, field, event): 
     357        bp_resource, bp, bc = event[3] 
     358        format = context.req.args.get('format', '').lower() 
     359        if bc: # A blog comment 
     360            if field == 'url': 
     361                return context.href.blog(bp.name) + '#comment-%d' % bc.number 
     362            elif field == 'title': 
     363                return tag(tag.em('Blog: '+bp.title), ' comment added') 
     364            elif field == 'description': 
     365                return format_to_oneliner(self.env, 
     366                            context(resource=bp_resource), bc.comment) 
     367        else: # A blog post 
     368            if field == 'url': 
     369                return context.href.blog(bp.name) 
     370            elif field == 'title': 
     371                if format == 'rss' and bp.version == 1: 
     372                    return tag(tag.em(bp.title)) 
     373                else: 
     374                    return tag(tag.em('Blog: '+bp.title), 
     375                            bp.version > 1 and ' edited' or ' created') 
     376            elif field == 'description': 
     377                if format.lower() == 'rss': 
     378                    if bp.version == 1: 
     379                        # In RSS, render first version in full view 
     380                        return format_to_html(self.env, 
     381                            context.from_request(context.req, 
     382                                    resource=bp_resource, absurls=True), 
     383                            bp.body) 
     384                    else: 
     385                        return format_to_html(self.env, 
     386                            context.from_request(context.req, 
     387                                    resource=bp_resource, absurls=True), 
     388                            bp.version_comment) 
     389                else: 
     390                    # Any other regular display format 
     391                    return format_to_oneliner(self.env, 
     392                            context(resource=bp_resource), 
     393                            bp.version==1 and bp.body or bp.version_comment) 
     394 
    297395    # ITemplateProvider methods 
    298396