source: peerreviewplugin/tags/0.12/3.1/codereview/timeline.py

Last change on this file was 17267, checked in by Cinc-th, 5 years ago

PeerReviewPlugin: show all status changes for reviews in the timeline. Before only the creation of a review (status new) was shown.

File size: 5.5 KB
Line 
1# -*- coding: utf-8 -*-
2#
3# Copyright (C) 2016 Cinc
4# All rights reserved.
5#
6# This software is licensed as described in the file COPYING.txt, which
7# you should have received as part of this distribution.
8#
9# Author: Cinc
10#
11from model import PeerReviewModel, PeerReviewerModel, ReviewFileModel
12from trac.core import Component, implements
13from trac.wiki.formatter import format_to_html
14from trac.resource import Resource, get_resource_url
15from trac.timeline.api import ITimelineEventProvider
16from trac.util.datefmt import from_utimestamp, to_utimestamp
17from trac.util.html import html as tag
18from trac.util.translation import _
19from trac.web.chrome import add_stylesheet
20
21
22class PeerReviewTimeline(Component):
23    """Provide code review events for the timeline.
24
25    [[BR]]
26    You need permission {{{CODE_REVIEW_VIEW}}} to see code review events.
27
28    '''Note:''' It is safe to disable this plugin when no timeline for code reviews should be shown.
29    """
30
31    implements(ITimelineEventProvider)
32
33    # ITimelineEventProvider methods
34
35    def get_timeline_filters(self, req):
36        if 'CODE_REVIEW_VIEW' in req.perm:
37            yield ('peerreview', _('Code Reviews'))
38
39    def get_timeline_events(self, req, start, stop, filters):
40        if 'peerreview' in filters:
41            ts_start = to_utimestamp(start)
42            ts_stop = to_utimestamp(stop)
43
44            coderev_resource = Resource('peerreview')
45
46            add_stylesheet(req, 'hw/css/peerreview.css')
47
48            def reviewers_for_review(rev_id):
49                rm = PeerReviewerModel(self.env)
50                rm.clear_props()
51                rm['review_id'] = rev_id
52                reviewers_lst = list(rm.list_matching_objects())
53
54                rev_list = ''
55                last = len(reviewers_lst) - 1
56                for idx, reviewer in enumerate(reviewers_lst):
57                    rev_list = rev_list + reviewer['reviewer']
58                    if idx != last:
59                        rev_list += ', '
60                return rev_list
61
62            def get_files_for_review_id(review_id):
63                """Get all files belonging to the given review id. Provide the number of comments if asked for."""
64                rfm = ReviewFileModel(self.env)
65                rfm.clear_props()
66                rfm['review_id'] = review_id
67                rev_files = list(rfm.list_matching_objects())
68                return rev_files
69
70            with self.env.db_query as db:
71                reviews = {}
72                for rid, t, author, field, oldvalue, newvalue \
73                        in db("""
74                                        SELECT pc.review_id, pc.time, pc.author,
75                                               pc.field, pc.oldvalue, pc.newvalue
76                                        FROM peerreview_change AS pc
77                                        WHERE pc.time>=%s AND pc.time<=%s
78                                        ORDER BY pc.time, pc.review_id
79                                        """, (ts_start, ts_stop)):
80                    if not (oldvalue or newvalue):
81                        # ignore empty change corresponding to custom field
82                        # created (None -> '') or deleted ('' -> None)
83                        continue
84                    if field == 'status':
85                        try:
86                            codereview, reviewers_list, coderev_page, files = reviews[rid]
87                        except KeyError:
88                            reviews[rid] = [PeerReviewModel(self.env, rid),
89                                            reviewers_for_review(rid),
90                                            coderev_resource(id=rid),
91                                            get_files_for_review_id(rid)
92                                            ]
93                            codereview, reviewers_list, coderev_page, files = reviews[rid]
94                        yield('peerreview', from_utimestamp(t), codereview['owner'],
95                              (coderev_page, codereview['name'], codereview['notes'],
96                               reviewers_list, oldvalue, newvalue, files))
97
98
99    def render_timeline_event(self, context, field, event):
100        codereview_page, name, notes, reviewersList, oldstatus, newstatus, files = event[3]
101
102        if field == 'url':
103            return get_resource_url(self.env, codereview_page, context.href)
104        if field == 'title':
105            return tag(_('Code review '), tag.em(name), " (%s)" % codereview_page.id,
106                       _(": Status changed from '%s' to '%s'" % (oldstatus, newstatus))
107                       )
108
109        def filelist():
110            ul = tag.ul()
111            for f in files:
112                ul.append(tag.li(
113                                 tag.a('%s @ %s' % (f['path'], f['changerevision']),
114                                       href='peerReviewPerform?IDFile=%s' % f['file_id']
115                                       )
116                                )
117                          )
118            return ul
119
120        if field == 'description':
121            return tag(_('Assigned to: '), tag.em(reviewersList),
122                       tag.div(_('Additional notes:')),
123                       tag.div(
124                           format_to_html(self.env, context, notes),
125                           class_='notes'
126                       ),
127                       tag.div(_('Files:')),
128                       filelist()
129                       )
Note: See TracBrowser for help on using the repository browser.