##// END OF EJS Templates
sidebar: expose status indicator for general comments which changed review status.
marcink -
r4490:6bf75c53 default
parent child Browse files
Show More

The requested changes are too big and content was truncated. Show full diff

@@ -1,203 +1,203 b''
1 # Copyright (C) 2016-2020 RhodeCode GmbH
1 # Copyright (C) 2016-2020 RhodeCode GmbH
2 #
2 #
3 # This program is free software: you can redistribute it and/or modify
3 # This program is free software: you can redistribute it and/or modify
4 # it under the terms of the GNU Affero General Public License, version 3
4 # it under the terms of the GNU Affero General Public License, version 3
5 # (only), as published by the Free Software Foundation.
5 # (only), as published by the Free Software Foundation.
6 #
6 #
7 # This program is distributed in the hope that it will be useful,
7 # This program is distributed in the hope that it will be useful,
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 # GNU General Public License for more details.
10 # GNU General Public License for more details.
11 #
11 #
12 # You should have received a copy of the GNU Affero General Public License
12 # You should have received a copy of the GNU Affero General Public License
13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 #
14 #
15 # This program is dual-licensed. If you wish to learn more about the
15 # This program is dual-licensed. If you wish to learn more about the
16 # RhodeCode Enterprise Edition, including its added features, Support services,
16 # RhodeCode Enterprise Edition, including its added features, Support services,
17 # and proprietary license terms, please see https://rhodecode.com/licenses/
17 # and proprietary license terms, please see https://rhodecode.com/licenses/
18
18
19 import logging
19 import logging
20
20
21 from rhodecode.translation import lazy_ugettext
21 from rhodecode.translation import lazy_ugettext
22 from rhodecode.events.repo import (RepoEvent, _commits_as_dict, _issues_as_dict)
22 from rhodecode.events.repo import (RepoEvent, _commits_as_dict, _issues_as_dict)
23
23
24 log = logging.getLogger(__name__)
24 log = logging.getLogger(__name__)
25
25
26
26
27 class PullRequestEvent(RepoEvent):
27 class PullRequestEvent(RepoEvent):
28 """
28 """
29 Base class for pull request events.
29 Base class for pull request events.
30
30
31 :param pullrequest: a :class:`PullRequest` instance
31 :param pullrequest: a :class:`PullRequest` instance
32 """
32 """
33
33
34 def __init__(self, pullrequest):
34 def __init__(self, pullrequest):
35 super(PullRequestEvent, self).__init__(pullrequest.target_repo)
35 super(PullRequestEvent, self).__init__(pullrequest.target_repo)
36 self.pullrequest = pullrequest
36 self.pullrequest = pullrequest
37
37
38 def as_dict(self):
38 def as_dict(self):
39 from rhodecode.lib.utils2 import md5_safe
39 from rhodecode.lib.utils2 import md5_safe
40 from rhodecode.model.pull_request import PullRequestModel
40 from rhodecode.model.pull_request import PullRequestModel
41 data = super(PullRequestEvent, self).as_dict()
41 data = super(PullRequestEvent, self).as_dict()
42
42
43 commits = _commits_as_dict(
43 commits = _commits_as_dict(
44 self,
44 self,
45 commit_ids=self.pullrequest.revisions,
45 commit_ids=self.pullrequest.revisions,
46 repos=[self.pullrequest.source_repo]
46 repos=[self.pullrequest.source_repo]
47 )
47 )
48 issues = _issues_as_dict(commits)
48 issues = _issues_as_dict(commits)
49 # calculate hashes of all commits for unique identifier of commits
49 # calculate hashes of all commits for unique identifier of commits
50 # inside that pull request
50 # inside that pull request
51 commits_hash = md5_safe(':'.join(x.get('raw_id', '') for x in commits))
51 commits_hash = md5_safe(':'.join(x.get('raw_id', '') for x in commits))
52
52
53 data.update({
53 data.update({
54 'pullrequest': {
54 'pullrequest': {
55 'title': self.pullrequest.title,
55 'title': self.pullrequest.title,
56 'issues': issues,
56 'issues': issues,
57 'pull_request_id': self.pullrequest.pull_request_id,
57 'pull_request_id': self.pullrequest.pull_request_id,
58 'url': PullRequestModel().get_url(
58 'url': PullRequestModel().get_url(
59 self.pullrequest, request=self.request),
59 self.pullrequest, request=self.request),
60 'permalink_url': PullRequestModel().get_url(
60 'permalink_url': PullRequestModel().get_url(
61 self.pullrequest, request=self.request, permalink=True),
61 self.pullrequest, request=self.request, permalink=True),
62 'shadow_url': PullRequestModel().get_shadow_clone_url(
62 'shadow_url': PullRequestModel().get_shadow_clone_url(
63 self.pullrequest, request=self.request),
63 self.pullrequest, request=self.request),
64 'status': self.pullrequest.calculated_review_status(),
64 'status': self.pullrequest.calculated_review_status(),
65 'commits_uid': commits_hash,
65 'commits_uid': commits_hash,
66 'commits': commits,
66 'commits': commits,
67 }
67 }
68 })
68 })
69 return data
69 return data
70
70
71
71
72 class PullRequestCreateEvent(PullRequestEvent):
72 class PullRequestCreateEvent(PullRequestEvent):
73 """
73 """
74 An instance of this class is emitted as an :term:`event` after a pull
74 An instance of this class is emitted as an :term:`event` after a pull
75 request is created.
75 request is created.
76 """
76 """
77 name = 'pullrequest-create'
77 name = 'pullrequest-create'
78 display_name = lazy_ugettext('pullrequest created')
78 display_name = lazy_ugettext('pullrequest created')
79 description = lazy_ugettext('Event triggered after pull request was created')
79 description = lazy_ugettext('Event triggered after pull request was created')
80
80
81
81
82 class PullRequestCloseEvent(PullRequestEvent):
82 class PullRequestCloseEvent(PullRequestEvent):
83 """
83 """
84 An instance of this class is emitted as an :term:`event` after a pull
84 An instance of this class is emitted as an :term:`event` after a pull
85 request is closed.
85 request is closed.
86 """
86 """
87 name = 'pullrequest-close'
87 name = 'pullrequest-close'
88 display_name = lazy_ugettext('pullrequest closed')
88 display_name = lazy_ugettext('pullrequest closed')
89 description = lazy_ugettext('Event triggered after pull request was closed')
89 description = lazy_ugettext('Event triggered after pull request was closed')
90
90
91
91
92 class PullRequestUpdateEvent(PullRequestEvent):
92 class PullRequestUpdateEvent(PullRequestEvent):
93 """
93 """
94 An instance of this class is emitted as an :term:`event` after a pull
94 An instance of this class is emitted as an :term:`event` after a pull
95 request's commits have been updated.
95 request's commits have been updated.
96 """
96 """
97 name = 'pullrequest-update'
97 name = 'pullrequest-update'
98 display_name = lazy_ugettext('pullrequest commits updated')
98 display_name = lazy_ugettext('pullrequest commits updated')
99 description = lazy_ugettext('Event triggered after pull requests was updated')
99 description = lazy_ugettext('Event triggered after pull requests was updated')
100
100
101
101
102 class PullRequestReviewEvent(PullRequestEvent):
102 class PullRequestReviewEvent(PullRequestEvent):
103 """
103 """
104 An instance of this class is emitted as an :term:`event` after a pull
104 An instance of this class is emitted as an :term:`event` after a pull
105 request review has changed. A status defines new status of review.
105 request review has changed. A status defines new status of review.
106 """
106 """
107 name = 'pullrequest-review'
107 name = 'pullrequest-review'
108 display_name = lazy_ugettext('pullrequest review changed')
108 display_name = lazy_ugettext('pullrequest review changed')
109 description = lazy_ugettext('Event triggered after a review status of a '
109 description = lazy_ugettext('Event triggered after a review status of a '
110 'pull requests has changed to other.')
110 'pull requests has changed to other.')
111
111
112 def __init__(self, pullrequest, status):
112 def __init__(self, pullrequest, status):
113 super(PullRequestReviewEvent, self).__init__(pullrequest)
113 super(PullRequestReviewEvent, self).__init__(pullrequest)
114 self.status = status
114 self.status = status
115
115
116
116
117 class PullRequestMergeEvent(PullRequestEvent):
117 class PullRequestMergeEvent(PullRequestEvent):
118 """
118 """
119 An instance of this class is emitted as an :term:`event` after a pull
119 An instance of this class is emitted as an :term:`event` after a pull
120 request is merged.
120 request is merged.
121 """
121 """
122 name = 'pullrequest-merge'
122 name = 'pullrequest-merge'
123 display_name = lazy_ugettext('pullrequest merged')
123 display_name = lazy_ugettext('pullrequest merged')
124 description = lazy_ugettext('Event triggered after a successful merge operation '
124 description = lazy_ugettext('Event triggered after a successful merge operation '
125 'was executed on a pull request')
125 'was executed on a pull request')
126
126
127
127
128 class PullRequestCommentEvent(PullRequestEvent):
128 class PullRequestCommentEvent(PullRequestEvent):
129 """
129 """
130 An instance of this class is emitted as an :term:`event` after a pull
130 An instance of this class is emitted as an :term:`event` after a pull
131 request comment is created.
131 request comment is created.
132 """
132 """
133 name = 'pullrequest-comment'
133 name = 'pullrequest-comment'
134 display_name = lazy_ugettext('pullrequest commented')
134 display_name = lazy_ugettext('pullrequest commented')
135 description = lazy_ugettext('Event triggered after a comment was made on a code '
135 description = lazy_ugettext('Event triggered after a comment was made on a code '
136 'in the pull request')
136 'in the pull request')
137
137
138 def __init__(self, pullrequest, comment):
138 def __init__(self, pullrequest, comment):
139 super(PullRequestCommentEvent, self).__init__(pullrequest)
139 super(PullRequestCommentEvent, self).__init__(pullrequest)
140 self.comment = comment
140 self.comment = comment
141
141
142 def as_dict(self):
142 def as_dict(self):
143 from rhodecode.model.comment import CommentsModel
143 from rhodecode.model.comment import CommentsModel
144 data = super(PullRequestCommentEvent, self).as_dict()
144 data = super(PullRequestCommentEvent, self).as_dict()
145
145
146 status = None
146 status = None
147 if self.comment.status_change:
147 if self.comment.status_change:
148 status = self.comment.status_change[0].status
148 status = self.comment.review_status
149
149
150 data.update({
150 data.update({
151 'comment': {
151 'comment': {
152 'status': status,
152 'status': status,
153 'text': self.comment.text,
153 'text': self.comment.text,
154 'type': self.comment.comment_type,
154 'type': self.comment.comment_type,
155 'file': self.comment.f_path,
155 'file': self.comment.f_path,
156 'line': self.comment.line_no,
156 'line': self.comment.line_no,
157 'version': self.comment.last_version,
157 'version': self.comment.last_version,
158 'url': CommentsModel().get_url(
158 'url': CommentsModel().get_url(
159 self.comment, request=self.request),
159 self.comment, request=self.request),
160 'permalink_url': CommentsModel().get_url(
160 'permalink_url': CommentsModel().get_url(
161 self.comment, request=self.request, permalink=True),
161 self.comment, request=self.request, permalink=True),
162 }
162 }
163 })
163 })
164 return data
164 return data
165
165
166
166
167 class PullRequestCommentEditEvent(PullRequestEvent):
167 class PullRequestCommentEditEvent(PullRequestEvent):
168 """
168 """
169 An instance of this class is emitted as an :term:`event` after a pull
169 An instance of this class is emitted as an :term:`event` after a pull
170 request comment is edited.
170 request comment is edited.
171 """
171 """
172 name = 'pullrequest-comment-edit'
172 name = 'pullrequest-comment-edit'
173 display_name = lazy_ugettext('pullrequest comment edited')
173 display_name = lazy_ugettext('pullrequest comment edited')
174 description = lazy_ugettext('Event triggered after a comment was edited on a code '
174 description = lazy_ugettext('Event triggered after a comment was edited on a code '
175 'in the pull request')
175 'in the pull request')
176
176
177 def __init__(self, pullrequest, comment):
177 def __init__(self, pullrequest, comment):
178 super(PullRequestCommentEditEvent, self).__init__(pullrequest)
178 super(PullRequestCommentEditEvent, self).__init__(pullrequest)
179 self.comment = comment
179 self.comment = comment
180
180
181 def as_dict(self):
181 def as_dict(self):
182 from rhodecode.model.comment import CommentsModel
182 from rhodecode.model.comment import CommentsModel
183 data = super(PullRequestCommentEditEvent, self).as_dict()
183 data = super(PullRequestCommentEditEvent, self).as_dict()
184
184
185 status = None
185 status = None
186 if self.comment.status_change:
186 if self.comment.status_change:
187 status = self.comment.status_change[0].status
187 status = self.comment.review_status
188
188
189 data.update({
189 data.update({
190 'comment': {
190 'comment': {
191 'status': status,
191 'status': status,
192 'text': self.comment.text,
192 'text': self.comment.text,
193 'type': self.comment.comment_type,
193 'type': self.comment.comment_type,
194 'file': self.comment.f_path,
194 'file': self.comment.f_path,
195 'line': self.comment.line_no,
195 'line': self.comment.line_no,
196 'version': self.comment.last_version,
196 'version': self.comment.last_version,
197 'url': CommentsModel().get_url(
197 'url': CommentsModel().get_url(
198 self.comment, request=self.request),
198 self.comment, request=self.request),
199 'permalink_url': CommentsModel().get_url(
199 'permalink_url': CommentsModel().get_url(
200 self.comment, request=self.request, permalink=True),
200 self.comment, request=self.request, permalink=True),
201 }
201 }
202 })
202 })
203 return data
203 return data
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
@@ -1,140 +1,142 b''
1 ## snippet for sidebar elements
1 ## snippet for sidebar elements
2 ## usage:
2 ## usage:
3 ## <%namespace name="sidebar" file="/base/sidebar.mako"/>
3 ## <%namespace name="sidebar" file="/base/sidebar.mako"/>
4 ## ${sidebar.comments_table()}
4 ## ${sidebar.comments_table()}
5 <%namespace name="base" file="/base/base.mako"/>
5 <%namespace name="base" file="/base/base.mako"/>
6
6
7 <%def name="comments_table(comments, counter_num, todo_comments=False, existing_ids=None, is_pr=True)">
7 <%def name="comments_table(comments, counter_num, todo_comments=False, existing_ids=None, is_pr=True)">
8 <%
8 <%
9 if todo_comments:
9 if todo_comments:
10 cls_ = 'todos-content-table'
10 cls_ = 'todos-content-table'
11 def sorter(entry):
11 def sorter(entry):
12 user_id = entry.author.user_id
12 user_id = entry.author.user_id
13 resolved = '1' if entry.resolved else '0'
13 resolved = '1' if entry.resolved else '0'
14 if user_id == c.rhodecode_user.user_id:
14 if user_id == c.rhodecode_user.user_id:
15 # own comments first
15 # own comments first
16 user_id = 0
16 user_id = 0
17 return '{}'.format(str(entry.comment_id).zfill(10000))
17 return '{}'.format(str(entry.comment_id).zfill(10000))
18 else:
18 else:
19 cls_ = 'comments-content-table'
19 cls_ = 'comments-content-table'
20 def sorter(entry):
20 def sorter(entry):
21 user_id = entry.author.user_id
21 user_id = entry.author.user_id
22 return '{}'.format(str(entry.comment_id).zfill(10000))
22 return '{}'.format(str(entry.comment_id).zfill(10000))
23
23
24 existing_ids = existing_ids or []
24 existing_ids = existing_ids or []
25
25
26 %>
26 %>
27
27
28 <table class="todo-table ${cls_}" data-total-count="${len(comments)}" data-counter="${counter_num}">
28 <table class="todo-table ${cls_}" data-total-count="${len(comments)}" data-counter="${counter_num}">
29
29
30 % for loop_obj, comment_obj in h.looper(reversed(sorted(comments, key=sorter))):
30 % for loop_obj, comment_obj in h.looper(reversed(sorted(comments, key=sorter))):
31 <%
31 <%
32 display = ''
32 display = ''
33 _cls = ''
33 _cls = ''
34 %>
34 %>
35
35
36 <%
36 <%
37 comment_ver_index = comment_obj.get_index_version(getattr(c, 'versions', []))
37 comment_ver_index = comment_obj.get_index_version(getattr(c, 'versions', []))
38 prev_comment_ver_index = 0
38 prev_comment_ver_index = 0
39 if loop_obj.previous:
39 if loop_obj.previous:
40 prev_comment_ver_index = loop_obj.previous.get_index_version(getattr(c, 'versions', []))
40 prev_comment_ver_index = loop_obj.previous.get_index_version(getattr(c, 'versions', []))
41
41
42 ver_info = None
42 ver_info = None
43 if getattr(c, 'versions', []):
43 if getattr(c, 'versions', []):
44 ver_info = c.versions[comment_ver_index-1] if comment_ver_index else None
44 ver_info = c.versions[comment_ver_index-1] if comment_ver_index else None
45 %>
45 %>
46 <% hidden_at_ver = comment_obj.outdated_at_version_js(c.at_version_num) %>
46 <% hidden_at_ver = comment_obj.outdated_at_version_js(c.at_version_num) %>
47 <% is_from_old_ver = comment_obj.older_than_version_js(c.at_version_num) %>
47 <% is_from_old_ver = comment_obj.older_than_version_js(c.at_version_num) %>
48 <%
48 <%
49 if (prev_comment_ver_index > comment_ver_index):
49 if (prev_comment_ver_index > comment_ver_index):
50 comments_ver_divider = comment_ver_index
50 comments_ver_divider = comment_ver_index
51 else:
51 else:
52 comments_ver_divider = None
52 comments_ver_divider = None
53 %>
53 %>
54
54
55 % if todo_comments:
55 % if todo_comments:
56 % if comment_obj.resolved:
56 % if comment_obj.resolved:
57 <% _cls = 'resolved-todo' %>
57 <% _cls = 'resolved-todo' %>
58 <% display = 'none' %>
58 <% display = 'none' %>
59 % endif
59 % endif
60 % else:
60 % else:
61 ## SKIP TODOs we display them in other area
61 ## SKIP TODOs we display them in other area
62 % if comment_obj.is_todo:
62 % if comment_obj.is_todo:
63 <% display = 'none' %>
63 <% display = 'none' %>
64 % endif
64 % endif
65 ## Skip outdated comments
65 ## Skip outdated comments
66 % if comment_obj.outdated:
66 % if comment_obj.outdated:
67 <% display = 'none' %>
67 <% display = 'none' %>
68 <% _cls = 'hidden-comment' %>
68 <% _cls = 'hidden-comment' %>
69 % endif
69 % endif
70 % endif
70 % endif
71
71
72 % if not todo_comments and comments_ver_divider:
72 % if not todo_comments and comments_ver_divider:
73 <tr class="old-comments-marker">
73 <tr class="old-comments-marker">
74 <td colspan="3">
74 <td colspan="3">
75 % if ver_info:
75 % if ver_info:
76 <code>v${comments_ver_divider} ${h.age_component(ver_info.created_on, time_is_local=True, tooltip=False)}</code>
76 <code>v${comments_ver_divider} ${h.age_component(ver_info.created_on, time_is_local=True, tooltip=False)}</code>
77 % else:
77 % else:
78 <code>v${comments_ver_divider}</code>
78 <code>v${comments_ver_divider}</code>
79 % endif
79 % endif
80 </td>
80 </td>
81 </tr>
81 </tr>
82
82
83 % endif
83 % endif
84
84
85 <tr class="${_cls}" style="display: ${display};" data-sidebar-comment-id="${comment_obj.comment_id}">
85 <tr class="${_cls}" style="display: ${display};" data-sidebar-comment-id="${comment_obj.comment_id}">
86 <td class="td-todo-number">
86 <td class="td-todo-number">
87 <%
87 <%
88 version_info = ''
88 version_info = ''
89 if is_pr:
89 if is_pr:
90 version_info = (' made in older version (v{})'.format(comment_ver_index) if is_from_old_ver == 'true' else ' made in this version')
90 version_info = (' made in older version (v{})'.format(comment_ver_index) if is_from_old_ver == 'true' else ' made in this version')
91 %>
91 %>
92
92 <script type="text/javascript">
93 <script type="text/javascript">
93 // closure function helper
94 // closure function helper
94 var sidebarComment${comment_obj.comment_id} = function() {
95 var sidebarComment${comment_obj.comment_id} = function() {
95 return renderTemplate('sideBarCommentHovercard', {
96 return renderTemplate('sideBarCommentHovercard', {
96 version_info: "${version_info}",
97 version_info: "${version_info}",
97 file_name: "${comment_obj.f_path}",
98 file_name: "${comment_obj.f_path}",
98 line_no: "${comment_obj.line_no}",
99 line_no: "${comment_obj.line_no}",
99 outdated: ${h.json.dumps(comment_obj.outdated)},
100 outdated: ${h.json.dumps(comment_obj.outdated)},
100 inline: ${h.json.dumps(comment_obj.is_inline)},
101 inline: ${h.json.dumps(comment_obj.is_inline)},
101 is_todo: ${h.json.dumps(comment_obj.is_todo)},
102 is_todo: ${h.json.dumps(comment_obj.is_todo)},
102 created_on: "${h.format_date(comment_obj.created_on)}",
103 created_on: "${h.format_date(comment_obj.created_on)}",
103 datetime: "${comment_obj.created_on}${h.get_timezone(comment_obj.created_on, time_is_local=True)}",
104 datetime: "${comment_obj.created_on}${h.get_timezone(comment_obj.created_on, time_is_local=True)}",
105 review_status: "${(comment_obj.review_status or '')}"
104 })
106 })
105 }
107 }
106 </script>
108 </script>
107
109
108 % if comment_obj.outdated:
110 % if comment_obj.outdated:
109 <i class="icon-comment-toggle tooltip-hovercard" data-hovercard-url="javascript:sidebarComment${comment_obj.comment_id}()"></i>
111 <i class="icon-comment-toggle tooltip-hovercard" data-hovercard-url="javascript:sidebarComment${comment_obj.comment_id}()"></i>
110 % elif comment_obj.is_inline:
112 % elif comment_obj.is_inline:
111 <i class="icon-code tooltip-hovercard" data-hovercard-url="javascript:sidebarComment${comment_obj.comment_id}()"></i>
113 <i class="icon-code tooltip-hovercard" data-hovercard-url="javascript:sidebarComment${comment_obj.comment_id}()"></i>
112 % else:
114 % else:
113 <i class="icon-comment tooltip-hovercard" data-hovercard-url="javascript:sidebarComment${comment_obj.comment_id}()"></i>
115 <i class="icon-comment tooltip-hovercard" data-hovercard-url="javascript:sidebarComment${comment_obj.comment_id}()"></i>
114 % endif
116 % endif
115
117
116 ## NEW, since refresh
118 ## NEW, since refresh
117 % if existing_ids and comment_obj.comment_id not in existing_ids:
119 % if existing_ids and comment_obj.comment_id not in existing_ids:
118 <span class="tag">NEW</span>
120 <span class="tag">NEW</span>
119 % endif
121 % endif
120 </td>
122 </td>
121
123
122 <td class="td-todo-gravatar">
124 <td class="td-todo-gravatar">
123 ${base.gravatar(comment_obj.author.email, 16, user=comment_obj.author, tooltip=True, extra_class=['no-margin'])}
125 ${base.gravatar(comment_obj.author.email, 16, user=comment_obj.author, tooltip=True, extra_class=['no-margin'])}
124 </td>
126 </td>
125 <td class="todo-comment-text-wrapper">
127 <td class="todo-comment-text-wrapper">
126 <div class="todo-comment-text ${('todo-resolved' if comment_obj.resolved else '')}">
128 <div class="todo-comment-text ${('todo-resolved' if comment_obj.resolved else '')}">
127 <a class="${('todo-resolved' if comment_obj.resolved else '')} permalink"
129 <a class="${('todo-resolved' if comment_obj.resolved else '')} permalink"
128 href="#comment-${comment_obj.comment_id}"
130 href="#comment-${comment_obj.comment_id}"
129 onclick="return Rhodecode.comments.scrollToComment($('#comment-${comment_obj.comment_id}'), 0, ${hidden_at_ver})">
131 onclick="return Rhodecode.comments.scrollToComment($('#comment-${comment_obj.comment_id}'), 0, ${hidden_at_ver})">
130
132
131 ${h.chop_at_smart(comment_obj.text, '\n', suffix_if_chopped='...')}
133 ${h.chop_at_smart(comment_obj.text, '\n', suffix_if_chopped='...')}
132 </a>
134 </a>
133 </div>
135 </div>
134 </td>
136 </td>
135 </tr>
137 </tr>
136 % endfor
138 % endfor
137
139
138 </table>
140 </table>
139
141
140 </%def> No newline at end of file
142 </%def>
@@ -1,518 +1,518 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 ## usage:
2 ## usage:
3 ## <%namespace name="comment" file="/changeset/changeset_file_comment.mako"/>
3 ## <%namespace name="comment" file="/changeset/changeset_file_comment.mako"/>
4 ## ${comment.comment_block(comment)}
4 ## ${comment.comment_block(comment)}
5 ##
5 ##
6
6
7 <%!
7 <%!
8 from rhodecode.lib import html_filters
8 from rhodecode.lib import html_filters
9 %>
9 %>
10
10
11 <%namespace name="base" file="/base/base.mako"/>
11 <%namespace name="base" file="/base/base.mako"/>
12 <%def name="comment_block(comment, inline=False, active_pattern_entries=None)">
12 <%def name="comment_block(comment, inline=False, active_pattern_entries=None)">
13
13
14 <%
14 <%
15 from rhodecode.model.comment import CommentsModel
15 from rhodecode.model.comment import CommentsModel
16 comment_model = CommentsModel()
16 comment_model = CommentsModel()
17 %>
17 %>
18 <% comment_ver = comment.get_index_version(getattr(c, 'versions', [])) %>
18 <% comment_ver = comment.get_index_version(getattr(c, 'versions', [])) %>
19 <% latest_ver = len(getattr(c, 'versions', [])) %>
19 <% latest_ver = len(getattr(c, 'versions', [])) %>
20
20
21 % if inline:
21 % if inline:
22 <% outdated_at_ver = comment.outdated_at_version(c.at_version_num) %>
22 <% outdated_at_ver = comment.outdated_at_version(c.at_version_num) %>
23 % else:
23 % else:
24 <% outdated_at_ver = comment.older_than_version(c.at_version_num) %>
24 <% outdated_at_ver = comment.older_than_version(c.at_version_num) %>
25 % endif
25 % endif
26
26
27 <div class="comment
27 <div class="comment
28 ${'comment-inline' if inline else 'comment-general'}
28 ${'comment-inline' if inline else 'comment-general'}
29 ${'comment-outdated' if outdated_at_ver else 'comment-current'}"
29 ${'comment-outdated' if outdated_at_ver else 'comment-current'}"
30 id="comment-${comment.comment_id}"
30 id="comment-${comment.comment_id}"
31 line="${comment.line_no}"
31 line="${comment.line_no}"
32 data-comment-id="${comment.comment_id}"
32 data-comment-id="${comment.comment_id}"
33 data-comment-type="${comment.comment_type}"
33 data-comment-type="${comment.comment_type}"
34 data-comment-renderer="${comment.renderer}"
34 data-comment-renderer="${comment.renderer}"
35 data-comment-text="${comment.text | html_filters.base64,n}"
35 data-comment-text="${comment.text | html_filters.base64,n}"
36 data-comment-line-no="${comment.line_no}"
36 data-comment-line-no="${comment.line_no}"
37 data-comment-inline=${h.json.dumps(inline)}
37 data-comment-inline=${h.json.dumps(inline)}
38 style="${'display: none;' if outdated_at_ver else ''}">
38 style="${'display: none;' if outdated_at_ver else ''}">
39
39
40 <div class="meta">
40 <div class="meta">
41 <div class="comment-type-label">
41 <div class="comment-type-label">
42 <div class="comment-label ${comment.comment_type or 'note'}" id="comment-label-${comment.comment_id}">
42 <div class="comment-label ${comment.comment_type or 'note'}" id="comment-label-${comment.comment_id}">
43
43
44 ## TODO COMMENT
44 ## TODO COMMENT
45 % if comment.comment_type == 'todo':
45 % if comment.comment_type == 'todo':
46 % if comment.resolved:
46 % if comment.resolved:
47 <div class="resolved tooltip" title="${_('Resolved by comment #{}').format(comment.resolved.comment_id)}">
47 <div class="resolved tooltip" title="${_('Resolved by comment #{}').format(comment.resolved.comment_id)}">
48 <i class="icon-flag-filled"></i>
48 <i class="icon-flag-filled"></i>
49 <a href="#comment-${comment.resolved.comment_id}">${comment.comment_type}</a>
49 <a href="#comment-${comment.resolved.comment_id}">${comment.comment_type}</a>
50 </div>
50 </div>
51 % else:
51 % else:
52 <div class="resolved tooltip" style="display: none">
52 <div class="resolved tooltip" style="display: none">
53 <span>${comment.comment_type}</span>
53 <span>${comment.comment_type}</span>
54 </div>
54 </div>
55 <div class="resolve tooltip" onclick="return Rhodecode.comments.createResolutionComment(${comment.comment_id});" title="${_('Click to create resolution comment.')}">
55 <div class="resolve tooltip" onclick="return Rhodecode.comments.createResolutionComment(${comment.comment_id});" title="${_('Click to create resolution comment.')}">
56 <i class="icon-flag-filled"></i>
56 <i class="icon-flag-filled"></i>
57 ${comment.comment_type}
57 ${comment.comment_type}
58 </div>
58 </div>
59 % endif
59 % endif
60 ## NOTE COMMENT
60 ## NOTE COMMENT
61 % else:
61 % else:
62 ## RESOLVED NOTE
62 ## RESOLVED NOTE
63 % if comment.resolved_comment:
63 % if comment.resolved_comment:
64 <div class="tooltip" title="${_('This comment resolves TODO #{}').format(comment.resolved_comment.comment_id)}">
64 <div class="tooltip" title="${_('This comment resolves TODO #{}').format(comment.resolved_comment.comment_id)}">
65 fix
65 fix
66 <a href="#comment-${comment.resolved_comment.comment_id}" onclick="Rhodecode.comments.scrollToComment($('#comment-${comment.resolved_comment.comment_id}'), 0, ${h.json.dumps(comment.resolved_comment.outdated)})">
66 <a href="#comment-${comment.resolved_comment.comment_id}" onclick="Rhodecode.comments.scrollToComment($('#comment-${comment.resolved_comment.comment_id}'), 0, ${h.json.dumps(comment.resolved_comment.outdated)})">
67 <span style="text-decoration: line-through">#${comment.resolved_comment.comment_id}</span>
67 <span style="text-decoration: line-through">#${comment.resolved_comment.comment_id}</span>
68 </a>
68 </a>
69 </div>
69 </div>
70 ## STATUS CHANGE NOTE
70 ## STATUS CHANGE NOTE
71 % elif not comment.is_inline and comment.status_change:
71 % elif not comment.is_inline and comment.status_change:
72 <%
72 <%
73 if comment.pull_request:
73 if comment.pull_request:
74 status_change_title = 'Status of review for pull request !{}'.format(comment.pull_request.pull_request_id)
74 status_change_title = 'Status of review for pull request !{}'.format(comment.pull_request.pull_request_id)
75 else:
75 else:
76 status_change_title = 'Status of review for commit {}'.format(h.short_id(comment.commit_id))
76 status_change_title = 'Status of review for commit {}'.format(h.short_id(comment.commit_id))
77 %>
77 %>
78
78
79 <i class="icon-circle review-status-${comment.status_change[0].status}"></i>
79 <i class="icon-circle review-status-${comment.review_status}"></i>
80 <div class="changeset-status-lbl tooltip" title="${status_change_title}">
80 <div class="changeset-status-lbl tooltip" title="${status_change_title}">
81 ${comment.status_change[0].status_lbl}
81 ${comment.review_status_lbl}
82 </div>
82 </div>
83 % else:
83 % else:
84 <div>
84 <div>
85 <i class="icon-comment"></i>
85 <i class="icon-comment"></i>
86 ${(comment.comment_type or 'note')}
86 ${(comment.comment_type or 'note')}
87 </div>
87 </div>
88 % endif
88 % endif
89 % endif
89 % endif
90
90
91 </div>
91 </div>
92 </div>
92 </div>
93
93
94 % if 0 and comment.status_change:
94 % if 0 and comment.status_change:
95 <div class="pull-left">
95 <div class="pull-left">
96 <span class="tag authortag tooltip" title="${_('Status from pull request.')}">
96 <span class="tag authortag tooltip" title="${_('Status from pull request.')}">
97 <a href="${h.route_path('pullrequest_show',repo_name=comment.pull_request.target_repo.repo_name,pull_request_id=comment.pull_request.pull_request_id)}">
97 <a href="${h.route_path('pullrequest_show',repo_name=comment.pull_request.target_repo.repo_name,pull_request_id=comment.pull_request.pull_request_id)}">
98 ${'!{}'.format(comment.pull_request.pull_request_id)}
98 ${'!{}'.format(comment.pull_request.pull_request_id)}
99 </a>
99 </a>
100 </span>
100 </span>
101 </div>
101 </div>
102 % endif
102 % endif
103
103
104 <div class="author ${'author-inline' if inline else 'author-general'}">
104 <div class="author ${'author-inline' if inline else 'author-general'}">
105 ${base.gravatar_with_user(comment.author.email, 16, tooltip=True)}
105 ${base.gravatar_with_user(comment.author.email, 16, tooltip=True)}
106 </div>
106 </div>
107
107
108 <div class="date">
108 <div class="date">
109 ${h.age_component(comment.modified_at, time_is_local=True)}
109 ${h.age_component(comment.modified_at, time_is_local=True)}
110 </div>
110 </div>
111
111
112 % if comment.pull_request and comment.pull_request.author.user_id == comment.author.user_id:
112 % if comment.pull_request and comment.pull_request.author.user_id == comment.author.user_id:
113 <span class="tag authortag tooltip" title="${_('Pull request author')}">
113 <span class="tag authortag tooltip" title="${_('Pull request author')}">
114 ${_('author')}
114 ${_('author')}
115 </span>
115 </span>
116 % endif
116 % endif
117
117
118 <%
118 <%
119 comment_version_selector = 'comment_versions_{}'.format(comment.comment_id)
119 comment_version_selector = 'comment_versions_{}'.format(comment.comment_id)
120 %>
120 %>
121
121
122 % if comment.history:
122 % if comment.history:
123 <div class="date">
123 <div class="date">
124
124
125 <input id="${comment_version_selector}" name="${comment_version_selector}"
125 <input id="${comment_version_selector}" name="${comment_version_selector}"
126 type="hidden"
126 type="hidden"
127 data-last-version="${comment.history[-1].version}">
127 data-last-version="${comment.history[-1].version}">
128
128
129 <script type="text/javascript">
129 <script type="text/javascript">
130
130
131 var preLoadVersionData = [
131 var preLoadVersionData = [
132 % for comment_history in comment.history:
132 % for comment_history in comment.history:
133 {
133 {
134 id: ${comment_history.comment_history_id},
134 id: ${comment_history.comment_history_id},
135 text: 'v${comment_history.version}',
135 text: 'v${comment_history.version}',
136 action: function () {
136 action: function () {
137 Rhodecode.comments.showVersion(
137 Rhodecode.comments.showVersion(
138 "${comment.comment_id}",
138 "${comment.comment_id}",
139 "${comment_history.comment_history_id}"
139 "${comment_history.comment_history_id}"
140 )
140 )
141 },
141 },
142 comment_version: "${comment_history.version}",
142 comment_version: "${comment_history.version}",
143 comment_author_username: "${comment_history.author.username}",
143 comment_author_username: "${comment_history.author.username}",
144 comment_author_gravatar: "${h.gravatar_url(comment_history.author.email, 16)}",
144 comment_author_gravatar: "${h.gravatar_url(comment_history.author.email, 16)}",
145 comment_created_on: '${h.age_component(comment_history.created_on, time_is_local=True)}',
145 comment_created_on: '${h.age_component(comment_history.created_on, time_is_local=True)}',
146 },
146 },
147 % endfor
147 % endfor
148 ]
148 ]
149 initVersionSelector("#${comment_version_selector}", {results: preLoadVersionData});
149 initVersionSelector("#${comment_version_selector}", {results: preLoadVersionData});
150
150
151 </script>
151 </script>
152
152
153 </div>
153 </div>
154 % else:
154 % else:
155 <div class="date" style="display: none">
155 <div class="date" style="display: none">
156 <input id="${comment_version_selector}" name="${comment_version_selector}"
156 <input id="${comment_version_selector}" name="${comment_version_selector}"
157 type="hidden"
157 type="hidden"
158 data-last-version="0">
158 data-last-version="0">
159 </div>
159 </div>
160 %endif
160 %endif
161
161
162 <div class="comment-links-block">
162 <div class="comment-links-block">
163
163
164 % if inline:
164 % if inline:
165 <a class="pr-version-inline" href="${request.current_route_path(_query=dict(version=comment.pull_request_version_id), _anchor='comment-{}'.format(comment.comment_id))}">
165 <a class="pr-version-inline" href="${request.current_route_path(_query=dict(version=comment.pull_request_version_id), _anchor='comment-{}'.format(comment.comment_id))}">
166 % if outdated_at_ver:
166 % if outdated_at_ver:
167 <code class="tooltip pr-version-num" title="${_('Outdated comment from pull request version v{0}, latest v{1}').format(comment_ver, latest_ver)}">outdated ${'v{}'.format(comment_ver)}</code>
167 <code class="tooltip pr-version-num" title="${_('Outdated comment from pull request version v{0}, latest v{1}').format(comment_ver, latest_ver)}">outdated ${'v{}'.format(comment_ver)}</code>
168 <code class="action-divider">|</code>
168 <code class="action-divider">|</code>
169 % elif comment_ver:
169 % elif comment_ver:
170 <code class="tooltip pr-version-num" title="${_('Comment from pull request version v{0}, latest v{1}').format(comment_ver, latest_ver)}">${'v{}'.format(comment_ver)}</code>
170 <code class="tooltip pr-version-num" title="${_('Comment from pull request version v{0}, latest v{1}').format(comment_ver, latest_ver)}">${'v{}'.format(comment_ver)}</code>
171 <code class="action-divider">|</code>
171 <code class="action-divider">|</code>
172 % endif
172 % endif
173 </a>
173 </a>
174 % else:
174 % else:
175 % if comment_ver:
175 % if comment_ver:
176
176
177 % if comment.outdated:
177 % if comment.outdated:
178 <a class="pr-version"
178 <a class="pr-version"
179 href="?version=${comment.pull_request_version_id}#comment-${comment.comment_id}"
179 href="?version=${comment.pull_request_version_id}#comment-${comment.comment_id}"
180 >
180 >
181 ${_('Outdated comment from pull request version v{0}, latest v{1}').format(comment_ver, latest_ver)}
181 ${_('Outdated comment from pull request version v{0}, latest v{1}').format(comment_ver, latest_ver)}
182 </a>
182 </a>
183 <code class="action-divider">|</code>
183 <code class="action-divider">|</code>
184 % else:
184 % else:
185 <a class="tooltip pr-version"
185 <a class="tooltip pr-version"
186 title="${_('Comment from pull request version v{0}, latest v{1}').format(comment_ver, latest_ver)}"
186 title="${_('Comment from pull request version v{0}, latest v{1}').format(comment_ver, latest_ver)}"
187 href="${h.route_path('pullrequest_show',repo_name=comment.pull_request.target_repo.repo_name,pull_request_id=comment.pull_request.pull_request_id, version=comment.pull_request_version_id)}"
187 href="${h.route_path('pullrequest_show',repo_name=comment.pull_request.target_repo.repo_name,pull_request_id=comment.pull_request.pull_request_id, version=comment.pull_request_version_id)}"
188 >
188 >
189 <code class="pr-version-num">${'v{}'.format(comment_ver)}</code>
189 <code class="pr-version-num">${'v{}'.format(comment_ver)}</code>
190 </a>
190 </a>
191 <code class="action-divider">|</code>
191 <code class="action-divider">|</code>
192 % endif
192 % endif
193
193
194 % endif
194 % endif
195 % endif
195 % endif
196
196
197 <details class="details-reset details-inline-block">
197 <details class="details-reset details-inline-block">
198 <summary class="noselect"><i class="icon-options cursor-pointer"></i></summary>
198 <summary class="noselect"><i class="icon-options cursor-pointer"></i></summary>
199 <details-menu class="details-dropdown">
199 <details-menu class="details-dropdown">
200
200
201 <div class="dropdown-item">
201 <div class="dropdown-item">
202 ${_('Comment')} #${comment.comment_id}
202 ${_('Comment')} #${comment.comment_id}
203 <span class="pull-right icon-clipboard clipboard-action" data-clipboard-text="${comment_model.get_url(comment,request, permalink=True, anchor='comment-{}'.format(comment.comment_id))}" title="${_('Copy permalink')}"></span>
203 <span class="pull-right icon-clipboard clipboard-action" data-clipboard-text="${comment_model.get_url(comment,request, permalink=True, anchor='comment-{}'.format(comment.comment_id))}" title="${_('Copy permalink')}"></span>
204 </div>
204 </div>
205
205
206 ## show delete comment if it's not a PR (regular comments) or it's PR that is not closed
206 ## show delete comment if it's not a PR (regular comments) or it's PR that is not closed
207 ## only super-admin, repo admin OR comment owner can delete, also hide delete if currently viewed comment is outdated
207 ## only super-admin, repo admin OR comment owner can delete, also hide delete if currently viewed comment is outdated
208 %if not outdated_at_ver and (not comment.pull_request or (comment.pull_request and not comment.pull_request.is_closed())):
208 %if not outdated_at_ver and (not comment.pull_request or (comment.pull_request and not comment.pull_request.is_closed())):
209 ## permissions to delete
209 ## permissions to delete
210 %if comment.immutable is False and (c.is_super_admin or h.HasRepoPermissionAny('repository.admin')(c.repo_name) or comment.author.user_id == c.rhodecode_user.user_id):
210 %if comment.immutable is False and (c.is_super_admin or h.HasRepoPermissionAny('repository.admin')(c.repo_name) or comment.author.user_id == c.rhodecode_user.user_id):
211 <div class="dropdown-divider"></div>
211 <div class="dropdown-divider"></div>
212 <div class="dropdown-item">
212 <div class="dropdown-item">
213 <a onclick="return Rhodecode.comments.editComment(this);" class="btn btn-link btn-sm edit-comment">${_('Edit')}</a>
213 <a onclick="return Rhodecode.comments.editComment(this);" class="btn btn-link btn-sm edit-comment">${_('Edit')}</a>
214 </div>
214 </div>
215 <div class="dropdown-item">
215 <div class="dropdown-item">
216 <a onclick="return Rhodecode.comments.deleteComment(this);" class="btn btn-link btn-sm btn-danger delete-comment">${_('Delete')}</a>
216 <a onclick="return Rhodecode.comments.deleteComment(this);" class="btn btn-link btn-sm btn-danger delete-comment">${_('Delete')}</a>
217 </div>
217 </div>
218 %else:
218 %else:
219 <div class="dropdown-divider"></div>
219 <div class="dropdown-divider"></div>
220 <div class="dropdown-item">
220 <div class="dropdown-item">
221 <a class="tooltip edit-comment link-disabled" disabled="disabled" title="${_('Action unavailable')}">${_('Edit')}</a>
221 <a class="tooltip edit-comment link-disabled" disabled="disabled" title="${_('Action unavailable')}">${_('Edit')}</a>
222 </div>
222 </div>
223 <div class="dropdown-item">
223 <div class="dropdown-item">
224 <a class="tooltip edit-comment link-disabled" disabled="disabled" title="${_('Action unavailable')}">${_('Delete')}</a>
224 <a class="tooltip edit-comment link-disabled" disabled="disabled" title="${_('Action unavailable')}">${_('Delete')}</a>
225 </div>
225 </div>
226 %endif
226 %endif
227 %else:
227 %else:
228 <div class="dropdown-divider"></div>
228 <div class="dropdown-divider"></div>
229 <div class="dropdown-item">
229 <div class="dropdown-item">
230 <a class="tooltip edit-comment link-disabled" disabled="disabled" title="${_('Action unavailable')}">${_('Edit')}</a>
230 <a class="tooltip edit-comment link-disabled" disabled="disabled" title="${_('Action unavailable')}">${_('Edit')}</a>
231 </div>
231 </div>
232 <div class="dropdown-item">
232 <div class="dropdown-item">
233 <a class="tooltip edit-comment link-disabled" disabled="disabled" title="${_('Action unavailable')}">${_('Delete')}</a>
233 <a class="tooltip edit-comment link-disabled" disabled="disabled" title="${_('Action unavailable')}">${_('Delete')}</a>
234 </div>
234 </div>
235 %endif
235 %endif
236 </details-menu>
236 </details-menu>
237 </details>
237 </details>
238
238
239 <code class="action-divider">|</code>
239 <code class="action-divider">|</code>
240 % if outdated_at_ver:
240 % if outdated_at_ver:
241 <a onclick="return Rhodecode.comments.prevOutdatedComment(this);" class="tooltip prev-comment" title="${_('Jump to the previous outdated comment')}"> <i class="icon-angle-left"></i> </a>
241 <a onclick="return Rhodecode.comments.prevOutdatedComment(this);" class="tooltip prev-comment" title="${_('Jump to the previous outdated comment')}"> <i class="icon-angle-left"></i> </a>
242 <a onclick="return Rhodecode.comments.nextOutdatedComment(this);" class="tooltip next-comment" title="${_('Jump to the next outdated comment')}"> <i class="icon-angle-right"></i></a>
242 <a onclick="return Rhodecode.comments.nextOutdatedComment(this);" class="tooltip next-comment" title="${_('Jump to the next outdated comment')}"> <i class="icon-angle-right"></i></a>
243 % else:
243 % else:
244 <a onclick="return Rhodecode.comments.prevComment(this);" class="tooltip prev-comment" title="${_('Jump to the previous comment')}"> <i class="icon-angle-left"></i></a>
244 <a onclick="return Rhodecode.comments.prevComment(this);" class="tooltip prev-comment" title="${_('Jump to the previous comment')}"> <i class="icon-angle-left"></i></a>
245 <a onclick="return Rhodecode.comments.nextComment(this);" class="tooltip next-comment" title="${_('Jump to the next comment')}"> <i class="icon-angle-right"></i></a>
245 <a onclick="return Rhodecode.comments.nextComment(this);" class="tooltip next-comment" title="${_('Jump to the next comment')}"> <i class="icon-angle-right"></i></a>
246 % endif
246 % endif
247
247
248 </div>
248 </div>
249 </div>
249 </div>
250 <div class="text">
250 <div class="text">
251 ${h.render(comment.text, renderer=comment.renderer, mentions=True, repo_name=getattr(c, 'repo_name', None), active_pattern_entries=active_pattern_entries)}
251 ${h.render(comment.text, renderer=comment.renderer, mentions=True, repo_name=getattr(c, 'repo_name', None), active_pattern_entries=active_pattern_entries)}
252 </div>
252 </div>
253
253
254 </div>
254 </div>
255 </%def>
255 </%def>
256
256
257 ## generate main comments
257 ## generate main comments
258 <%def name="generate_comments(comments, include_pull_request=False, is_pull_request=False)">
258 <%def name="generate_comments(comments, include_pull_request=False, is_pull_request=False)">
259 <%
259 <%
260 active_pattern_entries = h.get_active_pattern_entries(getattr(c, 'repo_name', None))
260 active_pattern_entries = h.get_active_pattern_entries(getattr(c, 'repo_name', None))
261 %>
261 %>
262
262
263 <div class="general-comments" id="comments">
263 <div class="general-comments" id="comments">
264 %for comment in comments:
264 %for comment in comments:
265 <div id="comment-tr-${comment.comment_id}">
265 <div id="comment-tr-${comment.comment_id}">
266 ## only render comments that are not from pull request, or from
266 ## only render comments that are not from pull request, or from
267 ## pull request and a status change
267 ## pull request and a status change
268 %if not comment.pull_request or (comment.pull_request and comment.status_change) or include_pull_request:
268 %if not comment.pull_request or (comment.pull_request and comment.status_change) or include_pull_request:
269 ${comment_block(comment, active_pattern_entries=active_pattern_entries)}
269 ${comment_block(comment, active_pattern_entries=active_pattern_entries)}
270 %endif
270 %endif
271 </div>
271 </div>
272 %endfor
272 %endfor
273 ## to anchor ajax comments
273 ## to anchor ajax comments
274 <div id="injected_page_comments"></div>
274 <div id="injected_page_comments"></div>
275 </div>
275 </div>
276 </%def>
276 </%def>
277
277
278
278
279 <%def name="comments(post_url, cur_status, is_pull_request=False, is_compare=False, change_status=True, form_extras=None)">
279 <%def name="comments(post_url, cur_status, is_pull_request=False, is_compare=False, change_status=True, form_extras=None)">
280
280
281 <div class="comments">
281 <div class="comments">
282 <%
282 <%
283 if is_pull_request:
283 if is_pull_request:
284 placeholder = _('Leave a comment on this Pull Request.')
284 placeholder = _('Leave a comment on this Pull Request.')
285 elif is_compare:
285 elif is_compare:
286 placeholder = _('Leave a comment on {} commits in this range.').format(len(form_extras))
286 placeholder = _('Leave a comment on {} commits in this range.').format(len(form_extras))
287 else:
287 else:
288 placeholder = _('Leave a comment on this Commit.')
288 placeholder = _('Leave a comment on this Commit.')
289 %>
289 %>
290
290
291 % if c.rhodecode_user.username != h.DEFAULT_USER:
291 % if c.rhodecode_user.username != h.DEFAULT_USER:
292 <div class="js-template" id="cb-comment-general-form-template">
292 <div class="js-template" id="cb-comment-general-form-template">
293 ## template generated for injection
293 ## template generated for injection
294 ${comment_form(form_type='general', review_statuses=c.commit_statuses, form_extras=form_extras)}
294 ${comment_form(form_type='general', review_statuses=c.commit_statuses, form_extras=form_extras)}
295 </div>
295 </div>
296
296
297 <div id="cb-comment-general-form-placeholder" class="comment-form ac">
297 <div id="cb-comment-general-form-placeholder" class="comment-form ac">
298 ## inject form here
298 ## inject form here
299 </div>
299 </div>
300 <script type="text/javascript">
300 <script type="text/javascript">
301 var lineNo = 'general';
301 var lineNo = 'general';
302 var resolvesCommentId = null;
302 var resolvesCommentId = null;
303 var generalCommentForm = Rhodecode.comments.createGeneralComment(
303 var generalCommentForm = Rhodecode.comments.createGeneralComment(
304 lineNo, "${placeholder}", resolvesCommentId);
304 lineNo, "${placeholder}", resolvesCommentId);
305
305
306 // set custom success callback on rangeCommit
306 // set custom success callback on rangeCommit
307 % if is_compare:
307 % if is_compare:
308 generalCommentForm.setHandleFormSubmit(function(o) {
308 generalCommentForm.setHandleFormSubmit(function(o) {
309 var self = generalCommentForm;
309 var self = generalCommentForm;
310
310
311 var text = self.cm.getValue();
311 var text = self.cm.getValue();
312 var status = self.getCommentStatus();
312 var status = self.getCommentStatus();
313 var commentType = self.getCommentType();
313 var commentType = self.getCommentType();
314
314
315 if (text === "" && !status) {
315 if (text === "" && !status) {
316 return;
316 return;
317 }
317 }
318
318
319 // we can pick which commits we want to make the comment by
319 // we can pick which commits we want to make the comment by
320 // selecting them via click on preview pane, this will alter the hidden inputs
320 // selecting them via click on preview pane, this will alter the hidden inputs
321 var cherryPicked = $('#changeset_compare_view_content .compare_select.hl').length > 0;
321 var cherryPicked = $('#changeset_compare_view_content .compare_select.hl').length > 0;
322
322
323 var commitIds = [];
323 var commitIds = [];
324 $('#changeset_compare_view_content .compare_select').each(function(el) {
324 $('#changeset_compare_view_content .compare_select').each(function(el) {
325 var commitId = this.id.replace('row-', '');
325 var commitId = this.id.replace('row-', '');
326 if ($(this).hasClass('hl') || !cherryPicked) {
326 if ($(this).hasClass('hl') || !cherryPicked) {
327 $("input[data-commit-id='{0}']".format(commitId)).val(commitId);
327 $("input[data-commit-id='{0}']".format(commitId)).val(commitId);
328 commitIds.push(commitId);
328 commitIds.push(commitId);
329 } else {
329 } else {
330 $("input[data-commit-id='{0}']".format(commitId)).val('')
330 $("input[data-commit-id='{0}']".format(commitId)).val('')
331 }
331 }
332 });
332 });
333
333
334 self.setActionButtonsDisabled(true);
334 self.setActionButtonsDisabled(true);
335 self.cm.setOption("readOnly", true);
335 self.cm.setOption("readOnly", true);
336 var postData = {
336 var postData = {
337 'text': text,
337 'text': text,
338 'changeset_status': status,
338 'changeset_status': status,
339 'comment_type': commentType,
339 'comment_type': commentType,
340 'commit_ids': commitIds,
340 'commit_ids': commitIds,
341 'csrf_token': CSRF_TOKEN
341 'csrf_token': CSRF_TOKEN
342 };
342 };
343
343
344 var submitSuccessCallback = function(o) {
344 var submitSuccessCallback = function(o) {
345 location.reload(true);
345 location.reload(true);
346 };
346 };
347 var submitFailCallback = function(){
347 var submitFailCallback = function(){
348 self.resetCommentFormState(text)
348 self.resetCommentFormState(text)
349 };
349 };
350 self.submitAjaxPOST(
350 self.submitAjaxPOST(
351 self.submitUrl, postData, submitSuccessCallback, submitFailCallback);
351 self.submitUrl, postData, submitSuccessCallback, submitFailCallback);
352 });
352 });
353 % endif
353 % endif
354
354
355 </script>
355 </script>
356 % else:
356 % else:
357 ## form state when not logged in
357 ## form state when not logged in
358 <div class="comment-form ac">
358 <div class="comment-form ac">
359
359
360 <div class="comment-area">
360 <div class="comment-area">
361 <div class="comment-area-header">
361 <div class="comment-area-header">
362 <ul class="nav-links clearfix">
362 <ul class="nav-links clearfix">
363 <li class="active">
363 <li class="active">
364 <a class="disabled" href="#edit-btn" disabled="disabled" onclick="return false">${_('Write')}</a>
364 <a class="disabled" href="#edit-btn" disabled="disabled" onclick="return false">${_('Write')}</a>
365 </li>
365 </li>
366 <li class="">
366 <li class="">
367 <a class="disabled" href="#preview-btn" disabled="disabled" onclick="return false">${_('Preview')}</a>
367 <a class="disabled" href="#preview-btn" disabled="disabled" onclick="return false">${_('Preview')}</a>
368 </li>
368 </li>
369 </ul>
369 </ul>
370 </div>
370 </div>
371
371
372 <div class="comment-area-write" style="display: block;">
372 <div class="comment-area-write" style="display: block;">
373 <div id="edit-container">
373 <div id="edit-container">
374 <div style="padding: 40px 0">
374 <div style="padding: 40px 0">
375 ${_('You need to be logged in to leave comments.')}
375 ${_('You need to be logged in to leave comments.')}
376 <a href="${h.route_path('login', _query={'came_from': h.current_route_path(request)})}">${_('Login now')}</a>
376 <a href="${h.route_path('login', _query={'came_from': h.current_route_path(request)})}">${_('Login now')}</a>
377 </div>
377 </div>
378 </div>
378 </div>
379 <div id="preview-container" class="clearfix" style="display: none;">
379 <div id="preview-container" class="clearfix" style="display: none;">
380 <div id="preview-box" class="preview-box"></div>
380 <div id="preview-box" class="preview-box"></div>
381 </div>
381 </div>
382 </div>
382 </div>
383
383
384 <div class="comment-area-footer">
384 <div class="comment-area-footer">
385 <div class="toolbar">
385 <div class="toolbar">
386 <div class="toolbar-text">
386 <div class="toolbar-text">
387 </div>
387 </div>
388 </div>
388 </div>
389 </div>
389 </div>
390 </div>
390 </div>
391
391
392 <div class="comment-footer">
392 <div class="comment-footer">
393 </div>
393 </div>
394
394
395 </div>
395 </div>
396 % endif
396 % endif
397
397
398 <script type="text/javascript">
398 <script type="text/javascript">
399 bindToggleButtons();
399 bindToggleButtons();
400 </script>
400 </script>
401 </div>
401 </div>
402 </%def>
402 </%def>
403
403
404
404
405 <%def name="comment_form(form_type, form_id='', lineno_id='{1}', review_statuses=None, form_extras=None)">
405 <%def name="comment_form(form_type, form_id='', lineno_id='{1}', review_statuses=None, form_extras=None)">
406
406
407 ## comment injected based on assumption that user is logged in
407 ## comment injected based on assumption that user is logged in
408 <form ${('id="{}"'.format(form_id) if form_id else '') |n} action="#" method="GET">
408 <form ${('id="{}"'.format(form_id) if form_id else '') |n} action="#" method="GET">
409
409
410 <div class="comment-area">
410 <div class="comment-area">
411 <div class="comment-area-header">
411 <div class="comment-area-header">
412 <div class="pull-left">
412 <div class="pull-left">
413 <ul class="nav-links clearfix">
413 <ul class="nav-links clearfix">
414 <li class="active">
414 <li class="active">
415 <a href="#edit-btn" tabindex="-1" id="edit-btn_${lineno_id}">${_('Write')}</a>
415 <a href="#edit-btn" tabindex="-1" id="edit-btn_${lineno_id}">${_('Write')}</a>
416 </li>
416 </li>
417 <li class="">
417 <li class="">
418 <a href="#preview-btn" tabindex="-1" id="preview-btn_${lineno_id}">${_('Preview')}</a>
418 <a href="#preview-btn" tabindex="-1" id="preview-btn_${lineno_id}">${_('Preview')}</a>
419 </li>
419 </li>
420 </ul>
420 </ul>
421 </div>
421 </div>
422 <div class="pull-right">
422 <div class="pull-right">
423 <span class="comment-area-text">${_('Mark as')}:</span>
423 <span class="comment-area-text">${_('Mark as')}:</span>
424 <select class="comment-type" id="comment_type_${lineno_id}" name="comment_type">
424 <select class="comment-type" id="comment_type_${lineno_id}" name="comment_type">
425 % for val in c.visual.comment_types:
425 % for val in c.visual.comment_types:
426 <option value="${val}">${val.upper()}</option>
426 <option value="${val}">${val.upper()}</option>
427 % endfor
427 % endfor
428 </select>
428 </select>
429 </div>
429 </div>
430 </div>
430 </div>
431
431
432 <div class="comment-area-write" style="display: block;">
432 <div class="comment-area-write" style="display: block;">
433 <div id="edit-container_${lineno_id}">
433 <div id="edit-container_${lineno_id}">
434 <textarea id="text_${lineno_id}" name="text" class="comment-block-ta ac-input"></textarea>
434 <textarea id="text_${lineno_id}" name="text" class="comment-block-ta ac-input"></textarea>
435 </div>
435 </div>
436 <div id="preview-container_${lineno_id}" class="clearfix" style="display: none;">
436 <div id="preview-container_${lineno_id}" class="clearfix" style="display: none;">
437 <div id="preview-box_${lineno_id}" class="preview-box"></div>
437 <div id="preview-box_${lineno_id}" class="preview-box"></div>
438 </div>
438 </div>
439 </div>
439 </div>
440
440
441 <div class="comment-area-footer comment-attachment-uploader">
441 <div class="comment-area-footer comment-attachment-uploader">
442 <div class="toolbar">
442 <div class="toolbar">
443
443
444 <div class="comment-attachment-text">
444 <div class="comment-attachment-text">
445 <div class="dropzone-text">
445 <div class="dropzone-text">
446 ${_("Drag'n Drop files here or")} <span class="link pick-attachment">${_('Choose your files')}</span>.<br>
446 ${_("Drag'n Drop files here or")} <span class="link pick-attachment">${_('Choose your files')}</span>.<br>
447 </div>
447 </div>
448 <div class="dropzone-upload" style="display:none">
448 <div class="dropzone-upload" style="display:none">
449 <i class="icon-spin animate-spin"></i> ${_('uploading...')}
449 <i class="icon-spin animate-spin"></i> ${_('uploading...')}
450 </div>
450 </div>
451 </div>
451 </div>
452
452
453 ## comments dropzone template, empty on purpose
453 ## comments dropzone template, empty on purpose
454 <div style="display: none" class="comment-attachment-uploader-template">
454 <div style="display: none" class="comment-attachment-uploader-template">
455 <div class="dz-file-preview" style="margin: 0">
455 <div class="dz-file-preview" style="margin: 0">
456 <div class="dz-error-message"></div>
456 <div class="dz-error-message"></div>
457 </div>
457 </div>
458 </div>
458 </div>
459
459
460 </div>
460 </div>
461 </div>
461 </div>
462 </div>
462 </div>
463
463
464 <div class="comment-footer">
464 <div class="comment-footer">
465
465
466 ## inject extra inputs into the form
466 ## inject extra inputs into the form
467 % if form_extras and isinstance(form_extras, (list, tuple)):
467 % if form_extras and isinstance(form_extras, (list, tuple)):
468 <div id="comment_form_extras">
468 <div id="comment_form_extras">
469 % for form_ex_el in form_extras:
469 % for form_ex_el in form_extras:
470 ${form_ex_el|n}
470 ${form_ex_el|n}
471 % endfor
471 % endfor
472 </div>
472 </div>
473 % endif
473 % endif
474
474
475 <div class="action-buttons">
475 <div class="action-buttons">
476 % if form_type != 'inline':
476 % if form_type != 'inline':
477 <div class="action-buttons-extra"></div>
477 <div class="action-buttons-extra"></div>
478 % endif
478 % endif
479
479
480 <input class="btn btn-success comment-button-input" id="save_${lineno_id}" name="save" type="submit" value="${_('Comment')}">
480 <input class="btn btn-success comment-button-input" id="save_${lineno_id}" name="save" type="submit" value="${_('Comment')}">
481
481
482 ## inline for has a file, and line-number together with cancel hide button.
482 ## inline for has a file, and line-number together with cancel hide button.
483 % if form_type == 'inline':
483 % if form_type == 'inline':
484 <input type="hidden" name="f_path" value="{0}">
484 <input type="hidden" name="f_path" value="{0}">
485 <input type="hidden" name="line" value="${lineno_id}">
485 <input type="hidden" name="line" value="${lineno_id}">
486 <button type="button" class="cb-comment-cancel" onclick="return Rhodecode.comments.cancelComment(this);">
486 <button type="button" class="cb-comment-cancel" onclick="return Rhodecode.comments.cancelComment(this);">
487 ${_('Cancel')}
487 ${_('Cancel')}
488 </button>
488 </button>
489 % endif
489 % endif
490 </div>
490 </div>
491
491
492 % if review_statuses:
492 % if review_statuses:
493 <div class="status_box">
493 <div class="status_box">
494 <select id="change_status_${lineno_id}" name="changeset_status">
494 <select id="change_status_${lineno_id}" name="changeset_status">
495 <option></option> ## Placeholder
495 <option></option> ## Placeholder
496 % for status, lbl in review_statuses:
496 % for status, lbl in review_statuses:
497 <option value="${status}" data-status="${status}">${lbl}</option>
497 <option value="${status}" data-status="${status}">${lbl}</option>
498 %if is_pull_request and change_status and status in ('approved', 'rejected'):
498 %if is_pull_request and change_status and status in ('approved', 'rejected'):
499 <option value="${status}_closed" data-status="${status}">${lbl} & ${_('Closed')}</option>
499 <option value="${status}_closed" data-status="${status}">${lbl} & ${_('Closed')}</option>
500 %endif
500 %endif
501 % endfor
501 % endfor
502 </select>
502 </select>
503 </div>
503 </div>
504 % endif
504 % endif
505
505
506 <div class="toolbar-text">
506 <div class="toolbar-text">
507 <% renderer_url = '<a href="%s">%s</a>' % (h.route_url('%s_help' % c.visual.default_renderer), c.visual.default_renderer.upper()) %>
507 <% renderer_url = '<a href="%s">%s</a>' % (h.route_url('%s_help' % c.visual.default_renderer), c.visual.default_renderer.upper()) %>
508 ${_('Comments parsed using {} syntax.').format(renderer_url)|n} <br/>
508 ${_('Comments parsed using {} syntax.').format(renderer_url)|n} <br/>
509 <span class="tooltip" title="${_('Use @username inside this text to send notification to this RhodeCode user')}">@mention</span>
509 <span class="tooltip" title="${_('Use @username inside this text to send notification to this RhodeCode user')}">@mention</span>
510 ${_('and')}
510 ${_('and')}
511 <span class="tooltip" title="${_('Start typing with / for certain actions to be triggered via text box.')}">`/` autocomplete</span>
511 <span class="tooltip" title="${_('Start typing with / for certain actions to be triggered via text box.')}">`/` autocomplete</span>
512 ${_('actions supported.')}
512 ${_('actions supported.')}
513 </div>
513 </div>
514 </div>
514 </div>
515
515
516 </form>
516 </form>
517
517
518 </%def> No newline at end of file
518 </%def>
@@ -1,236 +1,242 b''
1 <%text>
1 <%text>
2 <div style="display: none">
2 <div style="display: none">
3
3
4 <script>
4 <script>
5 var CG = new ColorGenerator();
5 var CG = new ColorGenerator();
6 </script>
6 </script>
7
7
8 <script id="ejs_gravatarWithUser" type="text/template" class="ejsTemplate">
8 <script id="ejs_gravatarWithUser" type="text/template" class="ejsTemplate">
9
9
10 <%
10 <%
11 if (size > 16) {
11 if (size > 16) {
12 var gravatar_class = 'gravatar gravatar-large';
12 var gravatar_class = 'gravatar gravatar-large';
13 } else {
13 } else {
14 var gravatar_class = 'gravatar';
14 var gravatar_class = 'gravatar';
15 }
15 }
16
16
17 if (tooltip) {
17 if (tooltip) {
18 var gravatar_class = gravatar_class + ' tooltip-hovercard';
18 var gravatar_class = gravatar_class + ' tooltip-hovercard';
19 }
19 }
20
20
21 var data_hovercard_alt = username;
21 var data_hovercard_alt = username;
22
22
23 %>
23 %>
24
24
25 <%
25 <%
26 if (show_disabled) {
26 if (show_disabled) {
27 var user_cls = 'user user-disabled';
27 var user_cls = 'user user-disabled';
28 } else {
28 } else {
29 var user_cls = 'user';
29 var user_cls = 'user';
30 }
30 }
31 var data_hovercard_url = pyroutes.url('hovercard_user', {"user_id": user_id})
31 var data_hovercard_url = pyroutes.url('hovercard_user', {"user_id": user_id})
32 %>
32 %>
33
33
34 <div class="rc-user">
34 <div class="rc-user">
35 <img class="<%= gravatar_class %>" height="<%= size %>" width="<%= size %>" data-hovercard-url="<%= data_hovercard_url %>" data-hovercard-alt="<%= data_hovercard_alt %>" src="<%- gravatar_url -%>">
35 <img class="<%= gravatar_class %>" height="<%= size %>" width="<%= size %>" data-hovercard-url="<%= data_hovercard_url %>" data-hovercard-alt="<%= data_hovercard_alt %>" src="<%- gravatar_url -%>">
36 <span class="<%= user_cls %>"> <%- user_link -%> </span>
36 <span class="<%= user_cls %>"> <%- user_link -%> </span>
37 </div>
37 </div>
38
38
39 </script>
39 </script>
40
40
41 <script id="ejs_reviewMemberEntry" type="text/template" class="ejsTemplate">
41 <script id="ejs_reviewMemberEntry" type="text/template" class="ejsTemplate">
42 <%
42 <%
43 if (create) {
43 if (create) {
44 var edit_visibility = 'visible';
44 var edit_visibility = 'visible';
45 } else {
45 } else {
46 var edit_visibility = 'hidden';
46 var edit_visibility = 'hidden';
47 }
47 }
48
48
49 if (member.user_group && member.user_group.vote_rule) {
49 if (member.user_group && member.user_group.vote_rule) {
50 var reviewGroup = '<i class="icon-user-group"></i>';
50 var reviewGroup = '<i class="icon-user-group"></i>';
51 var reviewGroupColor = CG.asRGB(CG.getColor(member.user_group.vote_rule));
51 var reviewGroupColor = CG.asRGB(CG.getColor(member.user_group.vote_rule));
52 } else {
52 } else {
53 var reviewGroup = null;
53 var reviewGroup = null;
54 var reviewGroupColor = 'transparent';
54 var reviewGroupColor = 'transparent';
55 }
55 }
56 var rule_show = rule_show || false;
56 var rule_show = rule_show || false;
57
57
58 if (rule_show) {
58 if (rule_show) {
59 var rule_visibility = 'table-cell';
59 var rule_visibility = 'table-cell';
60 } else {
60 } else {
61 var rule_visibility = 'none';
61 var rule_visibility = 'none';
62 }
62 }
63
63
64 %>
64 %>
65
65
66 <tr id="reviewer_<%= member.user_id %>" class="reviewer_entry" tooltip="Review Group" data-reviewer-user-id="<%= member.user_id %>">
66 <tr id="reviewer_<%= member.user_id %>" class="reviewer_entry" tooltip="Review Group" data-reviewer-user-id="<%= member.user_id %>">
67
67
68 <td style="width: 20px">
68 <td style="width: 20px">
69 <div class="reviewer_status tooltip" title="<%= review_status_label %>">
69 <div class="reviewer_status tooltip" title="<%= review_status_label %>">
70 <i class="icon-circle review-status-<%= review_status %>"></i>
70 <i class="icon-circle review-status-<%= review_status %>"></i>
71 </div>
71 </div>
72 </td>
72 </td>
73
73
74 <td>
74 <td>
75 <div id="reviewer_<%= member.user_id %>_name" class="reviewer_name">
75 <div id="reviewer_<%= member.user_id %>_name" class="reviewer_name">
76 <%-
76 <%-
77 renderTemplate('gravatarWithUser', {
77 renderTemplate('gravatarWithUser', {
78 'size': 16,
78 'size': 16,
79 'show_disabled': false,
79 'show_disabled': false,
80 'tooltip': true,
80 'tooltip': true,
81 'username': member.username,
81 'username': member.username,
82 'user_id': member.user_id,
82 'user_id': member.user_id,
83 'user_link': member.user_link,
83 'user_link': member.user_link,
84 'gravatar_url': member.gravatar_link
84 'gravatar_url': member.gravatar_link
85 })
85 })
86 %>
86 %>
87 <span class="tooltip presence-state" style="display: none" title="This users is currently at this page">
87 <span class="tooltip presence-state" style="display: none" title="This users is currently at this page">
88 <i class="icon-eye" style="color: #0ac878"></i>
88 <i class="icon-eye" style="color: #0ac878"></i>
89 </span>
89 </span>
90 </div>
90 </div>
91 </td>
91 </td>
92
92
93 <td style="width: 10px">
93 <td style="width: 10px">
94 <% if (reviewGroup !== null) { %>
94 <% if (reviewGroup !== null) { %>
95 <span class="tooltip" title="Member of review group from rule: `<%= member.user_group.name %>`" style="color: <%= reviewGroupColor %>">
95 <span class="tooltip" title="Member of review group from rule: `<%= member.user_group.name %>`" style="color: <%= reviewGroupColor %>">
96 <%- reviewGroup %>
96 <%- reviewGroup %>
97 </span>
97 </span>
98 <% } %>
98 <% } %>
99 </td>
99 </td>
100
100
101 <% if (mandatory) { %>
101 <% if (mandatory) { %>
102 <td style="text-align: right;width: 10px;">
102 <td style="text-align: right;width: 10px;">
103 <div class="reviewer_member_mandatory tooltip" title="Mandatory reviewer">
103 <div class="reviewer_member_mandatory tooltip" title="Mandatory reviewer">
104 <i class="icon-lock"></i>
104 <i class="icon-lock"></i>
105 </div>
105 </div>
106 </td>
106 </td>
107
107
108 <% } else { %>
108 <% } else { %>
109 <td style="text-align: right;width: 10px;">
109 <td style="text-align: right;width: 10px;">
110 <% if (allowed_to_update) { %>
110 <% if (allowed_to_update) { %>
111 <div class="reviewer_member_remove" onclick="reviewersController.removeReviewMember(<%= member.user_id %>, true)" style="visibility: <%= edit_visibility %>;">
111 <div class="reviewer_member_remove" onclick="reviewersController.removeReviewMember(<%= member.user_id %>, true)" style="visibility: <%= edit_visibility %>;">
112 <i class="icon-remove"></i>
112 <i class="icon-remove"></i>
113 </div>
113 </div>
114 <% } %>
114 <% } %>
115 </td>
115 </td>
116 <% } %>
116 <% } %>
117
117
118 </tr>
118 </tr>
119
119
120 <tr>
120 <tr>
121 <td colspan="4" style="display: <%= rule_visibility %>" class="pr-user-rule-container">
121 <td colspan="4" style="display: <%= rule_visibility %>" class="pr-user-rule-container">
122 <input type="hidden" name="__start__" value="reviewer:mapping">
122 <input type="hidden" name="__start__" value="reviewer:mapping">
123
123
124 <%if (member.user_group && member.user_group.vote_rule) { %>
124 <%if (member.user_group && member.user_group.vote_rule) { %>
125 <div class="reviewer_reason">
125 <div class="reviewer_reason">
126
126
127 <%if (member.user_group.vote_rule == -1) {%>
127 <%if (member.user_group.vote_rule == -1) {%>
128 - group votes required: ALL
128 - group votes required: ALL
129 <%} else {%>
129 <%} else {%>
130 - group votes required: <%= member.user_group.vote_rule %>
130 - group votes required: <%= member.user_group.vote_rule %>
131 <%}%>
131 <%}%>
132 </div>
132 </div>
133 <%} %>
133 <%} %>
134
134
135 <input type="hidden" name="__start__" value="reasons:sequence">
135 <input type="hidden" name="__start__" value="reasons:sequence">
136 <% for (var i = 0; i < reasons.length; i++) { %>
136 <% for (var i = 0; i < reasons.length; i++) { %>
137 <% var reason = reasons[i] %>
137 <% var reason = reasons[i] %>
138 <div class="reviewer_reason">- <%= reason %></div>
138 <div class="reviewer_reason">- <%= reason %></div>
139 <input type="hidden" name="reason" value="<%= reason %>">
139 <input type="hidden" name="reason" value="<%= reason %>">
140 <% } %>
140 <% } %>
141 <input type="hidden" name="__end__" value="reasons:sequence">
141 <input type="hidden" name="__end__" value="reasons:sequence">
142
142
143 <input type="hidden" name="__start__" value="rules:sequence">
143 <input type="hidden" name="__start__" value="rules:sequence">
144 <% for (var i = 0; i < member.rules.length; i++) { %>
144 <% for (var i = 0; i < member.rules.length; i++) { %>
145 <% var rule = member.rules[i] %>
145 <% var rule = member.rules[i] %>
146 <input type="hidden" name="rule_id" value="<%= rule %>">
146 <input type="hidden" name="rule_id" value="<%= rule %>">
147 <% } %>
147 <% } %>
148 <input type="hidden" name="__end__" value="rules:sequence">
148 <input type="hidden" name="__end__" value="rules:sequence">
149
149
150 <input id="reviewer_<%= member.user_id %>_input" type="hidden" value="<%= member.user_id %>" name="user_id" />
150 <input id="reviewer_<%= member.user_id %>_input" type="hidden" value="<%= member.user_id %>" name="user_id" />
151 <input type="hidden" name="mandatory" value="<%= mandatory %>"/>
151 <input type="hidden" name="mandatory" value="<%= mandatory %>"/>
152
152
153 <input type="hidden" name="__end__" value="reviewer:mapping">
153 <input type="hidden" name="__end__" value="reviewer:mapping">
154 </td>
154 </td>
155 </tr>
155 </tr>
156
156
157 </script>
157 </script>
158
158
159 <script id="ejs_commentVersion" type="text/template" class="ejsTemplate">
159 <script id="ejs_commentVersion" type="text/template" class="ejsTemplate">
160
160
161 <%
161 <%
162 if (size > 16) {
162 if (size > 16) {
163 var gravatar_class = 'gravatar gravatar-large';
163 var gravatar_class = 'gravatar gravatar-large';
164 } else {
164 } else {
165 var gravatar_class = 'gravatar';
165 var gravatar_class = 'gravatar';
166 }
166 }
167
167
168 %>
168 %>
169
169
170 <%
170 <%
171 if (show_disabled) {
171 if (show_disabled) {
172 var user_cls = 'user user-disabled';
172 var user_cls = 'user user-disabled';
173 } else {
173 } else {
174 var user_cls = 'user';
174 var user_cls = 'user';
175 }
175 }
176
176
177 %>
177 %>
178
178
179 <div style='line-height: 20px'>
179 <div style='line-height: 20px'>
180 <img style="margin: -3px 0" class="<%= gravatar_class %>" height="<%= size %>" width="<%= size %>" src="<%- gravatar_url -%>">
180 <img style="margin: -3px 0" class="<%= gravatar_class %>" height="<%= size %>" width="<%= size %>" src="<%- gravatar_url -%>">
181 <strong><%- user_name -%></strong>, <code>v<%- version -%></code> edited <%- timeago_component -%>
181 <strong><%- user_name -%></strong>, <code>v<%- version -%></code> edited <%- timeago_component -%>
182 </div>
182 </div>
183
183
184 </script>
184 </script>
185
185
186
186
187 <script id="ejs_sideBarCommentHovercard" type="text/template" class="ejsTemplate">
187 <script id="ejs_sideBarCommentHovercard" type="text/template" class="ejsTemplate">
188
188
189 <div>
189 <div>
190 <% if (is_todo) { %>
190 <% if (is_todo) { %>
191 <% if (inline) { %>
191 <% if (inline) { %>
192 <strong>Inline</strong> TODO on line: <%= line_no %>
192 <strong>Inline</strong> TODO on line: <%= line_no %>
193 <% if (version_info) { %>
193 <% if (version_info) { %>
194 <%= version_info %>
194 <%= version_info %>
195 <% } %>
195 <% } %>
196 <br/>
196 <br/>
197 File: <code><%- file_name -%></code>
197 File: <code><%- file_name -%></code>
198 <% } else { %>
198 <% } else { %>
199 <% if (review_status) { %>
200 <i class="icon-circle review-status-<%= review_status %>"></i>
201 <% } %>
199 <strong>General</strong> TODO
202 <strong>General</strong> TODO
200 <% if (version_info) { %>
203 <% if (version_info) { %>
201 <%= version_info %>
204 <%= version_info %>
202 <% } %>
205 <% } %>
203 <% } %>
206 <% } %>
204 <% } else { %>
207 <% } else { %>
205 <% if (inline) { %>
208 <% if (inline) { %>
206 <strong>Inline</strong> comment on line: <%= line_no %>
209 <strong>Inline</strong> comment on line: <%= line_no %>
207 <% if (version_info) { %>
210 <% if (version_info) { %>
208 <%= version_info %>
211 <%= version_info %>
209 <% } %>
212 <% } %>
210 <br/>
213 <br/>
211 File: <code><%- file_name -%></code>
214 File: <code><%- file_name -%></code>
212 <% } else { %>
215 <% } else { %>
216 <% if (review_status) { %>
217 <i class="icon-circle review-status-<%= review_status %>"></i>
218 <% } %>
213 <strong>General</strong> comment
219 <strong>General</strong> comment
214 <% if (version_info) { %>
220 <% if (version_info) { %>
215 <%= version_info %>
221 <%= version_info %>
216 <% } %>
222 <% } %>
217 <% } %>
223 <% } %>
218 <% } %>
224 <% } %>
219 <br/>
225 <br/>
220 Created:
226 Created:
221 <time class="timeago" title="<%= created_on %>" datetime="<%= datetime %>"><%= $.timeago(datetime) %></time>
227 <time class="timeago" title="<%= created_on %>" datetime="<%= datetime %>"><%= $.timeago(datetime) %></time>
222
228
223 </div>
229 </div>
224
230
225 </script>
231 </script>
226
232
227 ##// END OF EJS Templates
233 ##// END OF EJS Templates
228 </div>
234 </div>
229
235
230
236
231 <script>
237 <script>
232 // registers the templates into global cache
238 // registers the templates into global cache
233 registerTemplates();
239 registerTemplates();
234 </script>
240 </script>
235
241
236 </%text>
242 </%text>
General Comments 0
You need to be logged in to leave comments. Login now