Show More
@@ -0,0 +1,134 b'' | |||||
|
1 | ## snippet for sidebar elements | |||
|
2 | ## usage: | |||
|
3 | ## <%namespace name="sidebar" file="/base/sidebar.mako"/> | |||
|
4 | ## ${sidebar.comments_table()} | |||
|
5 | <%namespace name="base" file="/base/base.mako"/> | |||
|
6 | ||||
|
7 | <%def name="comments_table(comments, counter_num, todo_comments=False, existing_ids=None, is_pr=True)"> | |||
|
8 | <% | |||
|
9 | if todo_comments: | |||
|
10 | cls_ = 'todos-content-table' | |||
|
11 | def sorter(entry): | |||
|
12 | user_id = entry.author.user_id | |||
|
13 | resolved = '1' if entry.resolved else '0' | |||
|
14 | if user_id == c.rhodecode_user.user_id: | |||
|
15 | # own comments first | |||
|
16 | user_id = 0 | |||
|
17 | return '{}'.format(str(entry.comment_id).zfill(10000)) | |||
|
18 | else: | |||
|
19 | cls_ = 'comments-content-table' | |||
|
20 | def sorter(entry): | |||
|
21 | user_id = entry.author.user_id | |||
|
22 | return '{}'.format(str(entry.comment_id).zfill(10000)) | |||
|
23 | ||||
|
24 | existing_ids = existing_ids or [] | |||
|
25 | ||||
|
26 | %> | |||
|
27 | ||||
|
28 | <table class="todo-table ${cls_}" data-total-count="${len(comments)}" data-counter="${counter_num}"> | |||
|
29 | ||||
|
30 | % for loop_obj, comment_obj in h.looper(reversed(sorted(comments, key=sorter))): | |||
|
31 | <% | |||
|
32 | display = '' | |||
|
33 | _cls = '' | |||
|
34 | %> | |||
|
35 | ||||
|
36 | <% | |||
|
37 | comment_ver_index = comment_obj.get_index_version(getattr(c, 'versions', [])) | |||
|
38 | prev_comment_ver_index = 0 | |||
|
39 | if loop_obj.previous: | |||
|
40 | prev_comment_ver_index = loop_obj.previous.get_index_version(getattr(c, 'versions', [])) | |||
|
41 | ||||
|
42 | ver_info = None | |||
|
43 | if getattr(c, 'versions', []): | |||
|
44 | ver_info = c.versions[comment_ver_index-1] if comment_ver_index else None | |||
|
45 | %> | |||
|
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) %> | |||
|
48 | <% | |||
|
49 | if (prev_comment_ver_index > comment_ver_index): | |||
|
50 | comments_ver_divider = comment_ver_index | |||
|
51 | else: | |||
|
52 | comments_ver_divider = None | |||
|
53 | %> | |||
|
54 | ||||
|
55 | % if todo_comments: | |||
|
56 | % if comment_obj.resolved: | |||
|
57 | <% _cls = 'resolved-todo' %> | |||
|
58 | <% display = 'none' %> | |||
|
59 | % endif | |||
|
60 | % else: | |||
|
61 | ## SKIP TODOs we display them in other area | |||
|
62 | % if comment_obj.is_todo: | |||
|
63 | <% display = 'none' %> | |||
|
64 | % endif | |||
|
65 | ## Skip outdated comments | |||
|
66 | % if comment_obj.outdated: | |||
|
67 | <% display = 'none' %> | |||
|
68 | <% _cls = 'hidden-comment' %> | |||
|
69 | % endif | |||
|
70 | % endif | |||
|
71 | ||||
|
72 | % if not todo_comments and comments_ver_divider: | |||
|
73 | <tr class="old-comments-marker"> | |||
|
74 | <td colspan="3"> | |||
|
75 | % if ver_info: | |||
|
76 | <code>v${comments_ver_divider} ${h.age_component(ver_info.created_on, time_is_local=True, tooltip=False)}</code> | |||
|
77 | % else: | |||
|
78 | <code>v${comments_ver_divider}</code> | |||
|
79 | % endif | |||
|
80 | </td> | |||
|
81 | </tr> | |||
|
82 | ||||
|
83 | % endif | |||
|
84 | ||||
|
85 | <tr class="${_cls}" style="display: ${display};" data-sidebar-comment-id="${comment_obj.comment_id}"> | |||
|
86 | <td class="td-todo-number"> | |||
|
87 | ||||
|
88 | <a class="${('todo-resolved' if comment_obj.resolved else '')} permalink" | |||
|
89 | href="#comment-${comment_obj.comment_id}" | |||
|
90 | onclick="return Rhodecode.comments.scrollToComment($('#comment-${comment_obj.comment_id}'), 0, ${hidden_at_ver})"> | |||
|
91 | ||||
|
92 | <% | |||
|
93 | version_info = '' | |||
|
94 | if is_pr: | |||
|
95 | version_info = (' made in older version (v{})'.format(comment_ver_index) if is_from_old_ver == 'true' else ' made in this version') | |||
|
96 | %> | |||
|
97 | ||||
|
98 | % if todo_comments: | |||
|
99 | % if comment_obj.is_inline: | |||
|
100 | <i class="tooltip icon-code" title="Inline TODO comment${version_info}."></i> | |||
|
101 | % else: | |||
|
102 | <i class="tooltip icon-comment" title="General TODO comment${version_info}."></i> | |||
|
103 | % endif | |||
|
104 | % else: | |||
|
105 | % if comment_obj.outdated: | |||
|
106 | <i class="tooltip icon-comment-toggle" title="Inline Outdated made in v${comment_ver_index}."></i> | |||
|
107 | % elif comment_obj.is_inline: | |||
|
108 | <i class="tooltip icon-code" title="Inline comment${version_info}."></i> | |||
|
109 | % else: | |||
|
110 | <i class="tooltip icon-comment" title="General comment${version_info}."></i> | |||
|
111 | % endif | |||
|
112 | % endif | |||
|
113 | ||||
|
114 | </a> | |||
|
115 | ## NEW, since refresh | |||
|
116 | % if existing_ids and comment_obj.comment_id not in existing_ids: | |||
|
117 | <span class="tag">NEW</span> | |||
|
118 | % endif | |||
|
119 | </td> | |||
|
120 | ||||
|
121 | <td class="td-todo-gravatar"> | |||
|
122 | ${base.gravatar(comment_obj.author.email, 16, user=comment_obj.author, tooltip=True, extra_class=['no-margin'])} | |||
|
123 | </td> | |||
|
124 | <td class="todo-comment-text-wrapper"> | |||
|
125 | <div class="tooltip todo-comment-text timeago ${('todo-resolved' if comment_obj.resolved else '')} " title="${h.format_date(comment_obj.created_on)}" datetime="${comment_obj.created_on}${h.get_timezone(comment_obj.created_on, time_is_local=True)}"> | |||
|
126 | <code>${h.chop_at_smart(comment_obj.text, '\n', suffix_if_chopped='...')}</code> | |||
|
127 | </div> | |||
|
128 | </td> | |||
|
129 | </tr> | |||
|
130 | % endfor | |||
|
131 | ||||
|
132 | </table> | |||
|
133 | ||||
|
134 | </%def> No newline at end of file |
@@ -485,23 +485,10 b' class TestRepoCommitCommentsView(TestCon' | |||||
485 |
|
485 | |||
486 |
|
486 | |||
487 | def assert_comment_links(response, comments, inline_comments): |
|
487 | def assert_comment_links(response, comments, inline_comments): | |
488 | if comments == 1: |
|
488 | response.mustcontain( | |
489 | comments_text = "%d General" % comments |
|
489 | '<span class="display-none" id="general-comments-count">{}</span>'.format(comments)) | |
490 | else: |
|
490 | response.mustcontain( | |
491 | comments_text = "%d General" % comments |
|
491 | '<span class="display-none" id="inline-comments-count">{}</span>'.format(inline_comments)) | |
492 |
|
||||
493 | if inline_comments == 1: |
|
|||
494 | inline_comments_text = "%d Inline" % inline_comments |
|
|||
495 | else: |
|
|||
496 | inline_comments_text = "%d Inline" % inline_comments |
|
|||
497 |
|
492 | |||
498 | if comments: |
|
|||
499 | response.mustcontain('<a href="#comments">%s</a>,' % comments_text) |
|
|||
500 | else: |
|
|||
501 | response.mustcontain(comments_text) |
|
|||
502 |
|
493 | |||
503 | if inline_comments: |
|
494 | ||
504 | response.mustcontain( |
|
|||
505 | 'id="inline-comments-counter">%s' % inline_comments_text) |
|
|||
506 | else: |
|
|||
507 | response.mustcontain(inline_comments_text) |
|
@@ -18,8 +18,8 b'' | |||||
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
18 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
20 | |||
21 |
|
||||
22 | import logging |
|
21 | import logging | |
|
22 | import collections | |||
23 |
|
23 | |||
24 | from pyramid.httpexceptions import ( |
|
24 | from pyramid.httpexceptions import ( | |
25 | HTTPNotFound, HTTPBadRequest, HTTPFound, HTTPForbidden, HTTPConflict) |
|
25 | HTTPNotFound, HTTPBadRequest, HTTPFound, HTTPForbidden, HTTPConflict) | |
@@ -34,14 +34,14 b' from rhodecode.apps.file_store.exception' | |||||
34 | from rhodecode.lib import diffs, codeblocks |
|
34 | from rhodecode.lib import diffs, codeblocks | |
35 | from rhodecode.lib.auth import ( |
|
35 | from rhodecode.lib.auth import ( | |
36 | LoginRequired, HasRepoPermissionAnyDecorator, NotAnonymous, CSRFRequired) |
|
36 | LoginRequired, HasRepoPermissionAnyDecorator, NotAnonymous, CSRFRequired) | |
37 |
|
37 | from rhodecode.lib.ext_json import json | ||
38 | from rhodecode.lib.compat import OrderedDict |
|
38 | from rhodecode.lib.compat import OrderedDict | |
39 | from rhodecode.lib.diffs import ( |
|
39 | from rhodecode.lib.diffs import ( | |
40 | cache_diff, load_cached_diff, diff_cache_exist, get_diff_context, |
|
40 | cache_diff, load_cached_diff, diff_cache_exist, get_diff_context, | |
41 | get_diff_whitespace_flag) |
|
41 | get_diff_whitespace_flag) | |
42 | from rhodecode.lib.exceptions import StatusChangeOnClosedPullRequestError, CommentVersionMismatch |
|
42 | from rhodecode.lib.exceptions import StatusChangeOnClosedPullRequestError, CommentVersionMismatch | |
43 | import rhodecode.lib.helpers as h |
|
43 | import rhodecode.lib.helpers as h | |
44 | from rhodecode.lib.utils2 import safe_unicode, str2bool |
|
44 | from rhodecode.lib.utils2 import safe_unicode, str2bool, StrictAttributeDict | |
45 | from rhodecode.lib.vcs.backends.base import EmptyCommit |
|
45 | from rhodecode.lib.vcs.backends.base import EmptyCommit | |
46 | from rhodecode.lib.vcs.exceptions import ( |
|
46 | from rhodecode.lib.vcs.exceptions import ( | |
47 | RepositoryError, CommitDoesNotExistError) |
|
47 | RepositoryError, CommitDoesNotExistError) | |
@@ -87,7 +87,6 b' class RepoCommitsView(RepoAppView):' | |||||
87 | diff_limit = c.visual.cut_off_limit_diff |
|
87 | diff_limit = c.visual.cut_off_limit_diff | |
88 | file_limit = c.visual.cut_off_limit_file |
|
88 | file_limit = c.visual.cut_off_limit_file | |
89 |
|
89 | |||
90 |
|
||||
91 | # get ranges of commit ids if preset |
|
90 | # get ranges of commit ids if preset | |
92 | commit_range = commit_id_range.split('...')[:2] |
|
91 | commit_range = commit_id_range.split('...')[:2] | |
93 |
|
92 | |||
@@ -116,6 +115,7 b' class RepoCommitsView(RepoAppView):' | |||||
116 | except Exception: |
|
115 | except Exception: | |
117 | log.exception("General failure") |
|
116 | log.exception("General failure") | |
118 | raise HTTPNotFound() |
|
117 | raise HTTPNotFound() | |
|
118 | single_commit = len(c.commit_ranges) == 1 | |||
119 |
|
119 | |||
120 | c.changes = OrderedDict() |
|
120 | c.changes = OrderedDict() | |
121 | c.lines_added = 0 |
|
121 | c.lines_added = 0 | |
@@ -129,23 +129,48 b' class RepoCommitsView(RepoAppView):' | |||||
129 | c.inline_comments = [] |
|
129 | c.inline_comments = [] | |
130 | c.files = [] |
|
130 | c.files = [] | |
131 |
|
131 | |||
132 | c.statuses = [] |
|
|||
133 | c.comments = [] |
|
132 | c.comments = [] | |
134 | c.unresolved_comments = [] |
|
133 | c.unresolved_comments = [] | |
135 | c.resolved_comments = [] |
|
134 | c.resolved_comments = [] | |
136 | if len(c.commit_ranges) == 1: |
|
135 | ||
|
136 | # Single commit | |||
|
137 | if single_commit: | |||
137 | commit = c.commit_ranges[0] |
|
138 | commit = c.commit_ranges[0] | |
138 | c.comments = CommentsModel().get_comments( |
|
139 | c.comments = CommentsModel().get_comments( | |
139 | self.db_repo.repo_id, |
|
140 | self.db_repo.repo_id, | |
140 | revision=commit.raw_id) |
|
141 | revision=commit.raw_id) | |
141 | c.statuses.append(ChangesetStatusModel().get_status( |
|
142 | ||
142 | self.db_repo.repo_id, commit.raw_id)) |
|
|||
143 | # comments from PR |
|
143 | # comments from PR | |
144 | statuses = ChangesetStatusModel().get_statuses( |
|
144 | statuses = ChangesetStatusModel().get_statuses( | |
145 | self.db_repo.repo_id, commit.raw_id, |
|
145 | self.db_repo.repo_id, commit.raw_id, | |
146 | with_revisions=True) |
|
146 | with_revisions=True) | |
147 | prs = set(st.pull_request for st in statuses |
|
147 | ||
148 | if st.pull_request is not None) |
|
148 | prs = set() | |
|
149 | reviewers = list() | |||
|
150 | reviewers_duplicates = set() # to not have duplicates from multiple votes | |||
|
151 | for c_status in statuses: | |||
|
152 | ||||
|
153 | # extract associated pull-requests from votes | |||
|
154 | if c_status.pull_request: | |||
|
155 | prs.add(c_status.pull_request) | |||
|
156 | ||||
|
157 | # extract reviewers | |||
|
158 | _user_id = c_status.author.user_id | |||
|
159 | if _user_id not in reviewers_duplicates: | |||
|
160 | reviewers.append( | |||
|
161 | StrictAttributeDict({ | |||
|
162 | 'user': c_status.author, | |||
|
163 | ||||
|
164 | # fake attributed for commit, page that we don't have | |||
|
165 | # but we share the display with PR page | |||
|
166 | 'mandatory': False, | |||
|
167 | 'reasons': [], | |||
|
168 | 'rule_user_group_data': lambda: None | |||
|
169 | }) | |||
|
170 | ) | |||
|
171 | reviewers_duplicates.add(_user_id) | |||
|
172 | ||||
|
173 | c.allowed_reviewers = reviewers | |||
149 | # from associated statuses, check the pull requests, and |
|
174 | # from associated statuses, check the pull requests, and | |
150 | # show comments from them |
|
175 | # show comments from them | |
151 | for pr in prs: |
|
176 | for pr in prs: | |
@@ -156,6 +181,37 b' class RepoCommitsView(RepoAppView):' | |||||
156 | c.resolved_comments = CommentsModel()\ |
|
181 | c.resolved_comments = CommentsModel()\ | |
157 | .get_commit_resolved_todos(commit.raw_id) |
|
182 | .get_commit_resolved_todos(commit.raw_id) | |
158 |
|
183 | |||
|
184 | c.inline_comments_flat = CommentsModel()\ | |||
|
185 | .get_commit_inline_comments(commit.raw_id) | |||
|
186 | ||||
|
187 | review_statuses = ChangesetStatusModel().aggregate_votes_by_user( | |||
|
188 | statuses, reviewers) | |||
|
189 | ||||
|
190 | c.commit_review_status = ChangesetStatus.STATUS_NOT_REVIEWED | |||
|
191 | ||||
|
192 | c.commit_set_reviewers_data_json = collections.OrderedDict({'reviewers': []}) | |||
|
193 | ||||
|
194 | for review_obj, member, reasons, mandatory, status in review_statuses: | |||
|
195 | member_reviewer = h.reviewer_as_json( | |||
|
196 | member, reasons=reasons, mandatory=mandatory, | |||
|
197 | user_group=None | |||
|
198 | ) | |||
|
199 | ||||
|
200 | current_review_status = status[0][1].status if status else ChangesetStatus.STATUS_NOT_REVIEWED | |||
|
201 | member_reviewer['review_status'] = current_review_status | |||
|
202 | member_reviewer['review_status_label'] = h.commit_status_lbl(current_review_status) | |||
|
203 | member_reviewer['allowed_to_update'] = False | |||
|
204 | c.commit_set_reviewers_data_json['reviewers'].append(member_reviewer) | |||
|
205 | ||||
|
206 | c.commit_set_reviewers_data_json = json.dumps(c.commit_set_reviewers_data_json) | |||
|
207 | ||||
|
208 | # NOTE(marcink): this uses the same voting logic as in pull-requests | |||
|
209 | c.commit_review_status = ChangesetStatusModel().calculate_status(review_statuses) | |||
|
210 | c.commit_broadcast_channel = u'/repo${}$/commit/{}'.format( | |||
|
211 | c.repo_name, | |||
|
212 | commit.raw_id | |||
|
213 | ) | |||
|
214 | ||||
159 | diff = None |
|
215 | diff = None | |
160 | # Iterate over ranges (default commit view is always one commit) |
|
216 | # Iterate over ranges (default commit view is always one commit) | |
161 | for commit in c.commit_ranges: |
|
217 | for commit in c.commit_ranges: | |
@@ -397,6 +453,7 b' class RepoCommitsView(RepoAppView):' | |||||
397 | } |
|
453 | } | |
398 | if comment: |
|
454 | if comment: | |
399 | c.co = comment |
|
455 | c.co = comment | |
|
456 | c.at_version_num = 0 | |||
400 | rendered_comment = render( |
|
457 | rendered_comment = render( | |
401 | 'rhodecode:templates/changeset/changeset_comment_block.mako', |
|
458 | 'rhodecode:templates/changeset/changeset_comment_block.mako', | |
402 | self._get_template_context(c), self.request) |
|
459 | self._get_template_context(c), self.request) |
@@ -39,7 +39,7 b' from rhodecode.lib.ext_json import json' | |||||
39 | from rhodecode.lib.auth import ( |
|
39 | from rhodecode.lib.auth import ( | |
40 | LoginRequired, HasRepoPermissionAny, HasRepoPermissionAnyDecorator, |
|
40 | LoginRequired, HasRepoPermissionAny, HasRepoPermissionAnyDecorator, | |
41 | NotAnonymous, CSRFRequired) |
|
41 | NotAnonymous, CSRFRequired) | |
42 | from rhodecode.lib.utils2 import str2bool, safe_str, safe_unicode |
|
42 | from rhodecode.lib.utils2 import str2bool, safe_str, safe_unicode, safe_int | |
43 | from rhodecode.lib.vcs.backends.base import EmptyCommit, UpdateFailureReason |
|
43 | from rhodecode.lib.vcs.backends.base import EmptyCommit, UpdateFailureReason | |
44 | from rhodecode.lib.vcs.exceptions import ( |
|
44 | from rhodecode.lib.vcs.exceptions import ( | |
45 | CommitDoesNotExistError, RepositoryRequirementError, EmptyRepositoryError) |
|
45 | CommitDoesNotExistError, RepositoryRequirementError, EmptyRepositoryError) | |
@@ -474,9 +474,6 b' class RepoPullRequestsView(RepoAppView, ' | |||||
474 |
|
474 | |||
475 | c.pull_request_set_reviewers_data_json = json.dumps(c.pull_request_set_reviewers_data_json) |
|
475 | c.pull_request_set_reviewers_data_json = json.dumps(c.pull_request_set_reviewers_data_json) | |
476 |
|
476 | |||
477 |
|
||||
478 |
|
||||
479 |
|
||||
480 | general_comments, inline_comments = \ |
|
477 | general_comments, inline_comments = \ | |
481 | self.register_comments_vars(c, pull_request_latest, versions) |
|
478 | self.register_comments_vars(c, pull_request_latest, versions) | |
482 |
|
479 | |||
@@ -980,7 +977,7 b' class RepoPullRequestsView(RepoAppView, ' | |||||
980 | version = self.request.GET.get('version') |
|
977 | version = self.request.GET.get('version') | |
981 |
|
978 | |||
982 | _render = self.request.get_partial_renderer( |
|
979 | _render = self.request.get_partial_renderer( | |
983 |
'rhodecode:templates/ |
|
980 | 'rhodecode:templates/base/sidebar.mako') | |
984 | c = _render.get_call_context() |
|
981 | c = _render.get_call_context() | |
985 |
|
982 | |||
986 | (pull_request_latest, |
|
983 | (pull_request_latest, | |
@@ -999,7 +996,11 b' class RepoPullRequestsView(RepoAppView, ' | |||||
999 |
|
996 | |||
1000 | self.register_comments_vars(c, pull_request_latest, versions) |
|
997 | self.register_comments_vars(c, pull_request_latest, versions) | |
1001 | all_comments = c.inline_comments_flat + c.comments |
|
998 | all_comments = c.inline_comments_flat + c.comments | |
1002 | return _render('comments_table', all_comments, len(all_comments)) |
|
999 | ||
|
1000 | existing_ids = filter( | |||
|
1001 | lambda e: e, map(safe_int, self.request.POST.getall('comments[]'))) | |||
|
1002 | return _render('comments_table', all_comments, len(all_comments), | |||
|
1003 | existing_ids=existing_ids) | |||
1003 |
|
1004 | |||
1004 | @LoginRequired() |
|
1005 | @LoginRequired() | |
1005 | @NotAnonymous() |
|
1006 | @NotAnonymous() | |
@@ -1017,7 +1018,7 b' class RepoPullRequestsView(RepoAppView, ' | |||||
1017 | version = self.request.GET.get('version') |
|
1018 | version = self.request.GET.get('version') | |
1018 |
|
1019 | |||
1019 | _render = self.request.get_partial_renderer( |
|
1020 | _render = self.request.get_partial_renderer( | |
1020 |
'rhodecode:templates/ |
|
1021 | 'rhodecode:templates/base/sidebar.mako') | |
1021 | c = _render.get_call_context() |
|
1022 | c = _render.get_call_context() | |
1022 | (pull_request_latest, |
|
1023 | (pull_request_latest, | |
1023 | pull_request_at_ver, |
|
1024 | pull_request_at_ver, | |
@@ -1039,7 +1040,10 b' class RepoPullRequestsView(RepoAppView, ' | |||||
1039 | .get_pull_request_resolved_todos(pull_request) |
|
1040 | .get_pull_request_resolved_todos(pull_request) | |
1040 |
|
1041 | |||
1041 | all_comments = c.unresolved_comments + c.resolved_comments |
|
1042 | all_comments = c.unresolved_comments + c.resolved_comments | |
1042 | return _render('comments_table', all_comments, len(c.unresolved_comments), todo_comments=True) |
|
1043 | existing_ids = filter( | |
|
1044 | lambda e: e, map(safe_int, self.request.POST.getall('comments[]'))) | |||
|
1045 | return _render('comments_table', all_comments, len(c.unresolved_comments), | |||
|
1046 | todo_comments=True, existing_ids=existing_ids) | |||
1043 |
|
1047 | |||
1044 | @LoginRequired() |
|
1048 | @LoginRequired() | |
1045 | @NotAnonymous() |
|
1049 | @NotAnonymous() |
@@ -354,34 +354,37 b' class ChangesetStatusModel(BaseModel):' | |||||
354 | Session().add(new_status) |
|
354 | Session().add(new_status) | |
355 | return new_statuses |
|
355 | return new_statuses | |
356 |
|
356 | |||
|
357 | def aggregate_votes_by_user(self, commit_statuses, reviewers_data): | |||
|
358 | ||||
|
359 | commit_statuses_map = collections.defaultdict(list) | |||
|
360 | for st in commit_statuses: | |||
|
361 | commit_statuses_map[st.author.username] += [st] | |||
|
362 | ||||
|
363 | reviewers = [] | |||
|
364 | ||||
|
365 | def version(commit_status): | |||
|
366 | return commit_status.version | |||
|
367 | ||||
|
368 | for obj in reviewers_data: | |||
|
369 | if not obj.user: | |||
|
370 | continue | |||
|
371 | statuses = commit_statuses_map.get(obj.user.username, None) | |||
|
372 | if statuses: | |||
|
373 | status_groups = itertools.groupby( | |||
|
374 | sorted(statuses, key=version), version) | |||
|
375 | statuses = [(x, list(y)[0]) for x, y in status_groups] | |||
|
376 | ||||
|
377 | reviewers.append((obj, obj.user, obj.reasons, obj.mandatory, statuses)) | |||
|
378 | ||||
|
379 | return reviewers | |||
|
380 | ||||
357 | def reviewers_statuses(self, pull_request): |
|
381 | def reviewers_statuses(self, pull_request): | |
358 | _commit_statuses = self.get_statuses( |
|
382 | _commit_statuses = self.get_statuses( | |
359 | pull_request.source_repo, |
|
383 | pull_request.source_repo, | |
360 | pull_request=pull_request, |
|
384 | pull_request=pull_request, | |
361 | with_revisions=True) |
|
385 | with_revisions=True) | |
362 |
|
386 | |||
363 | commit_statuses = collections.defaultdict(list) |
|
387 | return self.aggregate_votes_by_user(_commit_statuses, pull_request.reviewers) | |
364 | for st in _commit_statuses: |
|
|||
365 | commit_statuses[st.author.username] += [st] |
|
|||
366 |
|
||||
367 | pull_request_reviewers = [] |
|
|||
368 |
|
||||
369 | def version(commit_status): |
|
|||
370 | return commit_status.version |
|
|||
371 |
|
||||
372 | for obj in pull_request.reviewers: |
|
|||
373 | if not obj.user: |
|
|||
374 | continue |
|
|||
375 | statuses = commit_statuses.get(obj.user.username, None) |
|
|||
376 | if statuses: |
|
|||
377 | status_groups = itertools.groupby( |
|
|||
378 | sorted(statuses, key=version), version) |
|
|||
379 | statuses = [(x, list(y)[0]) for x, y in status_groups] |
|
|||
380 |
|
||||
381 | pull_request_reviewers.append( |
|
|||
382 | (obj, obj.user, obj.reasons, obj.mandatory, statuses)) |
|
|||
383 |
|
||||
384 | return pull_request_reviewers |
|
|||
385 |
|
388 | |||
386 | def calculated_review_status(self, pull_request, reviewers_statuses=None): |
|
389 | def calculated_review_status(self, pull_request, reviewers_statuses=None): | |
387 | """ |
|
390 | """ |
@@ -228,6 +228,14 b' class CommentsModel(BaseModel):' | |||||
228 |
|
228 | |||
229 | return todos |
|
229 | return todos | |
230 |
|
230 | |||
|
231 | def get_commit_inline_comments(self, commit_id): | |||
|
232 | inline_comments = Session().query(ChangesetComment) \ | |||
|
233 | .filter(ChangesetComment.line_no != None) \ | |||
|
234 | .filter(ChangesetComment.f_path != None) \ | |||
|
235 | .filter(ChangesetComment.revision == commit_id) | |||
|
236 | inline_comments = inline_comments.all() | |||
|
237 | return inline_comments | |||
|
238 | ||||
231 | def _log_audit_action(self, action, action_data, auth_user, comment): |
|
239 | def _log_audit_action(self, action, action_data, auth_user, comment): | |
232 | audit_logger.store( |
|
240 | audit_logger.store( | |
233 | action=action, |
|
241 | action=action, |
@@ -55,3 +55,16 b'' | |||||
55 | margin: 0 auto 35px auto; |
|
55 | margin: 0 auto 35px auto; | |
56 | } |
|
56 | } | |
57 | } |
|
57 | } | |
|
58 | ||||
|
59 | .alert-text-success { | |||
|
60 | color: @alert1; | |||
|
61 | ||||
|
62 | } | |||
|
63 | ||||
|
64 | .alert-text-error { | |||
|
65 | color: @alert2; | |||
|
66 | } | |||
|
67 | ||||
|
68 | .alert-text-warning { | |||
|
69 | color: @alert3; | |||
|
70 | } |
@@ -254,7 +254,7 b' input[type="button"] {' | |||||
254 |
|
254 | |||
255 | .btn-group-actions { |
|
255 | .btn-group-actions { | |
256 | position: relative; |
|
256 | position: relative; | |
257 |
z-index: |
|
257 | z-index: 50; | |
258 |
|
258 | |||
259 | &:not(.open) .btn-action-switcher-container { |
|
259 | &:not(.open) .btn-action-switcher-container { | |
260 | display: none; |
|
260 | display: none; |
@@ -1078,10 +1078,16 b' input.filediff-collapse-state {' | |||||
1078 | background: @color5; |
|
1078 | background: @color5; | |
1079 | color: white; |
|
1079 | color: white; | |
1080 | } |
|
1080 | } | |
|
1081 | ||||
1081 | &[op="comments"] { /* comments on file */ |
|
1082 | &[op="comments"] { /* comments on file */ | |
1082 | background: @grey4; |
|
1083 | background: @grey4; | |
1083 | color: white; |
|
1084 | color: white; | |
1084 | } |
|
1085 | } | |
|
1086 | ||||
|
1087 | &[op="options"] { /* context menu */ | |||
|
1088 | background: @grey6; | |||
|
1089 | color: black; | |||
|
1090 | } | |||
1085 | } |
|
1091 | } | |
1086 | } |
|
1092 | } | |
1087 |
|
1093 |
@@ -31,6 +31,10 b' a { cursor: pointer; }' | |||||
31 | clear: both; |
|
31 | clear: both; | |
32 | } |
|
32 | } | |
33 |
|
33 | |||
|
34 | .display-none { | |||
|
35 | display: none; | |||
|
36 | } | |||
|
37 | ||||
34 | .pull-right { |
|
38 | .pull-right { | |
35 | float: right !important; |
|
39 | float: right !important; | |
36 | } |
|
40 | } |
@@ -83,6 +83,11 b' body {' | |||||
83 | } |
|
83 | } | |
84 | } |
|
84 | } | |
85 |
|
85 | |||
|
86 | .flex-container { | |||
|
87 | display: flex; | |||
|
88 | justify-content: space-between; | |||
|
89 | } | |||
|
90 | ||||
86 | .action-link{ |
|
91 | .action-link{ | |
87 | margin-left: @padding; |
|
92 | margin-left: @padding; | |
88 | padding-left: @padding; |
|
93 | padding-left: @padding; | |
@@ -482,6 +487,15 b' ul.auth_plugins {' | |||||
482 | text-align: left; |
|
487 | text-align: left; | |
483 | overflow: hidden; |
|
488 | overflow: hidden; | |
484 | white-space: pre-line; |
|
489 | white-space: pre-line; | |
|
490 | padding-top: 5px | |||
|
491 | } | |||
|
492 | ||||
|
493 | #add_reviewer { | |||
|
494 | padding-top: 10px; | |||
|
495 | } | |||
|
496 | ||||
|
497 | #add_reviewer_input { | |||
|
498 | padding-top: 10px | |||
485 | } |
|
499 | } | |
486 |
|
500 | |||
487 | .pr-details-title-author-pref { |
|
501 | .pr-details-title-author-pref { | |
@@ -1169,9 +1183,12 b' label {' | |||||
1169 | a { |
|
1183 | a { | |
1170 | color: @grey5 |
|
1184 | color: @grey5 | |
1171 | } |
|
1185 | } | |
1172 | @media screen and (max-width: 1200px) { |
|
1186 | ||
|
1187 | // 1024px or smaller | |||
|
1188 | @media screen and (max-width: 1180px) { | |||
1173 | display: none; |
|
1189 | display: none; | |
1174 | } |
|
1190 | } | |
|
1191 | ||||
1175 | } |
|
1192 | } | |
1176 |
|
1193 | |||
1177 | img { |
|
1194 | img { | |
@@ -1553,6 +1570,7 b' table.integrations {' | |||||
1553 | width: 16px; |
|
1570 | width: 16px; | |
1554 | padding: 0; |
|
1571 | padding: 0; | |
1555 | color: black; |
|
1572 | color: black; | |
|
1573 | cursor: pointer; | |||
1556 | } |
|
1574 | } | |
1557 |
|
1575 | |||
1558 | .reviewer_member_mandatory_remove { |
|
1576 | .reviewer_member_mandatory_remove { | |
@@ -1682,7 +1700,7 b' table.group_members {' | |||||
1682 | } |
|
1700 | } | |
1683 |
|
1701 | |||
1684 | .reviewer_ac .ac-input { |
|
1702 | .reviewer_ac .ac-input { | |
1685 |
width: |
|
1703 | width: 100%; | |
1686 | margin-bottom: 1em; |
|
1704 | margin-bottom: 1em; | |
1687 | } |
|
1705 | } | |
1688 |
|
1706 | |||
@@ -2756,7 +2774,7 b' table.rctable td.td-search-results div {' | |||||
2756 | } |
|
2774 | } | |
2757 |
|
2775 | |||
2758 | #help_kb .modal-content{ |
|
2776 | #help_kb .modal-content{ | |
2759 |
max-width: |
|
2777 | max-width: 800px; | |
2760 | margin: 10% auto; |
|
2778 | margin: 10% auto; | |
2761 |
|
2779 | |||
2762 | table{ |
|
2780 | table{ | |
@@ -3053,4 +3071,141 b' form.markup-form {' | |||||
3053 |
|
3071 | |||
3054 | .pr-hovercard-title { |
|
3072 | .pr-hovercard-title { | |
3055 | padding-top: 5px; |
|
3073 | padding-top: 5px; | |
3056 | } No newline at end of file |
|
3074 | } | |
|
3075 | ||||
|
3076 | .action-divider { | |||
|
3077 | opacity: 0.5; | |||
|
3078 | } | |||
|
3079 | ||||
|
3080 | .details-inline-block { | |||
|
3081 | display: inline-block; | |||
|
3082 | position: relative; | |||
|
3083 | } | |||
|
3084 | ||||
|
3085 | .details-inline-block summary { | |||
|
3086 | list-style: none; | |||
|
3087 | } | |||
|
3088 | ||||
|
3089 | details:not([open]) > :not(summary) { | |||
|
3090 | display: none !important; | |||
|
3091 | } | |||
|
3092 | ||||
|
3093 | .details-reset > summary { | |||
|
3094 | list-style: none; | |||
|
3095 | } | |||
|
3096 | ||||
|
3097 | .details-reset > summary::-webkit-details-marker { | |||
|
3098 | display: none; | |||
|
3099 | } | |||
|
3100 | ||||
|
3101 | .details-dropdown { | |||
|
3102 | position: absolute; | |||
|
3103 | top: 100%; | |||
|
3104 | width: 185px; | |||
|
3105 | list-style: none; | |||
|
3106 | background-color: #fff; | |||
|
3107 | background-clip: padding-box; | |||
|
3108 | border: 1px solid @grey5; | |||
|
3109 | box-shadow: 0 8px 24px rgba(149, 157, 165, .2); | |||
|
3110 | left: -150px; | |||
|
3111 | text-align: left; | |||
|
3112 | z-index: 90; | |||
|
3113 | } | |||
|
3114 | ||||
|
3115 | .dropdown-divider { | |||
|
3116 | display: block; | |||
|
3117 | height: 0; | |||
|
3118 | margin: 8px 0; | |||
|
3119 | border-top: 1px solid @grey5; | |||
|
3120 | } | |||
|
3121 | ||||
|
3122 | .dropdown-item { | |||
|
3123 | display: block; | |||
|
3124 | padding: 4px 8px 4px 16px; | |||
|
3125 | overflow: hidden; | |||
|
3126 | text-overflow: ellipsis; | |||
|
3127 | white-space: nowrap; | |||
|
3128 | font-weight: normal; | |||
|
3129 | } | |||
|
3130 | ||||
|
3131 | .right-sidebar { | |||
|
3132 | position: fixed; | |||
|
3133 | top: 0px; | |||
|
3134 | bottom: 0; | |||
|
3135 | right: 0; | |||
|
3136 | ||||
|
3137 | background: #fafafa; | |||
|
3138 | z-index: 50; | |||
|
3139 | } | |||
|
3140 | ||||
|
3141 | .right-sidebar { | |||
|
3142 | border-left: 1px solid @grey5; | |||
|
3143 | } | |||
|
3144 | ||||
|
3145 | .right-sidebar.right-sidebar-expanded { | |||
|
3146 | width: 300px; | |||
|
3147 | overflow: scroll; | |||
|
3148 | } | |||
|
3149 | ||||
|
3150 | .right-sidebar.right-sidebar-collapsed { | |||
|
3151 | width: 40px; | |||
|
3152 | padding: 0; | |||
|
3153 | display: block; | |||
|
3154 | overflow: hidden; | |||
|
3155 | } | |||
|
3156 | ||||
|
3157 | .sidenav { | |||
|
3158 | float: right; | |||
|
3159 | will-change: min-height; | |||
|
3160 | background: #fafafa; | |||
|
3161 | width: 100%; | |||
|
3162 | } | |||
|
3163 | ||||
|
3164 | .sidebar-toggle { | |||
|
3165 | height: 30px; | |||
|
3166 | text-align: center; | |||
|
3167 | margin: 15px 0px 0 0; | |||
|
3168 | } | |||
|
3169 | ||||
|
3170 | .sidebar-toggle a { | |||
|
3171 | ||||
|
3172 | } | |||
|
3173 | ||||
|
3174 | .sidebar-content { | |||
|
3175 | margin-left: 15px; | |||
|
3176 | margin-right: 15px; | |||
|
3177 | } | |||
|
3178 | ||||
|
3179 | .sidebar-heading { | |||
|
3180 | font-size: 1.2em; | |||
|
3181 | font-weight: 700; | |||
|
3182 | margin-top: 10px; | |||
|
3183 | } | |||
|
3184 | ||||
|
3185 | .sidebar-element { | |||
|
3186 | margin-top: 20px; | |||
|
3187 | } | |||
|
3188 | ||||
|
3189 | .right-sidebar-collapsed-state { | |||
|
3190 | display: flex; | |||
|
3191 | flex-direction: column; | |||
|
3192 | justify-content: center; | |||
|
3193 | align-items: center; | |||
|
3194 | padding: 0 10px; | |||
|
3195 | cursor: pointer; | |||
|
3196 | font-size: 1.3em; | |||
|
3197 | margin: 0 -15px; | |||
|
3198 | } | |||
|
3199 | ||||
|
3200 | .right-sidebar-collapsed-state:hover { | |||
|
3201 | background-color: @grey5; | |||
|
3202 | } | |||
|
3203 | ||||
|
3204 | .old-comments-marker { | |||
|
3205 | text-align: left; | |||
|
3206 | } | |||
|
3207 | ||||
|
3208 | .old-comments-marker td { | |||
|
3209 | padding-top: 15px; | |||
|
3210 | border-bottom: 1px solid @grey5; | |||
|
3211 | } |
@@ -790,7 +790,7 b' input {' | |||||
790 |
|
790 | |||
791 | &.main_filter_input { |
|
791 | &.main_filter_input { | |
792 | padding: 5px 10px; |
|
792 | padding: 5px 10px; | |
793 | min-width: 340px; |
|
793 | ||
794 | color: @grey7; |
|
794 | color: @grey7; | |
795 | background: @black; |
|
795 | background: @black; | |
796 | min-height: 18px; |
|
796 | min-height: 18px; | |
@@ -800,11 +800,34 b' input {' | |||||
800 | color: @grey2 !important; |
|
800 | color: @grey2 !important; | |
801 | background: white !important; |
|
801 | background: white !important; | |
802 | } |
|
802 | } | |
|
803 | ||||
803 | &:focus { |
|
804 | &:focus { | |
804 | color: @grey2 !important; |
|
805 | color: @grey2 !important; | |
805 | background: white !important; |
|
806 | background: white !important; | |
806 | } |
|
807 | } | |
|
808 | ||||
|
809 | min-width: 360px; | |||
|
810 | ||||
|
811 | @media screen and (max-width: 1600px) { | |||
|
812 | min-width: 300px; | |||
807 | } |
|
813 | } | |
|
814 | @media screen and (max-width: 1500px) { | |||
|
815 | min-width: 280px; | |||
|
816 | } | |||
|
817 | @media screen and (max-width: 1400px) { | |||
|
818 | min-width: 260px; | |||
|
819 | } | |||
|
820 | @media screen and (max-width: 1300px) { | |||
|
821 | min-width: 240px; | |||
|
822 | } | |||
|
823 | @media screen and (max-width: 1200px) { | |||
|
824 | min-width: 220px; | |||
|
825 | } | |||
|
826 | @media screen and (max-width: 720px) { | |||
|
827 | min-width: 140px; | |||
|
828 | } | |||
|
829 | } | |||
|
830 | ||||
808 | } |
|
831 | } | |
809 |
|
832 | |||
810 |
|
833 |
@@ -168,6 +168,7 b'' | |||||
168 | .icon-remove:before { content: '\e810'; } /* 'ξ ' */ |
|
168 | .icon-remove:before { content: '\e810'; } /* 'ξ ' */ | |
169 | .icon-fork:before { content: '\e811'; } /* 'ξ ' */ |
|
169 | .icon-fork:before { content: '\e811'; } /* 'ξ ' */ | |
170 | .icon-more:before { content: '\e812'; } /* 'ξ ' */ |
|
170 | .icon-more:before { content: '\e812'; } /* 'ξ ' */ | |
|
171 | .icon-options:before { content: '\e812'; } /* 'ξ ' */ | |||
171 | .icon-search:before { content: '\e813'; } /* 'ξ ' */ |
|
172 | .icon-search:before { content: '\e813'; } /* 'ξ ' */ | |
172 | .icon-scissors:before { content: '\e814'; } /* 'ξ ' */ |
|
173 | .icon-scissors:before { content: '\e814'; } /* 'ξ ' */ | |
173 | .icon-download:before { content: '\e815'; } /* 'ξ ' */ |
|
174 | .icon-download:before { content: '\e815'; } /* 'ξ ' */ | |
@@ -251,6 +252,7 b'' | |||||
251 | // TRANSFORM |
|
252 | // TRANSFORM | |
252 | .icon-merge:before {transform: rotate(180deg);} |
|
253 | .icon-merge:before {transform: rotate(180deg);} | |
253 | .icon-wide-mode:before {transform: rotate(90deg);} |
|
254 | .icon-wide-mode:before {transform: rotate(90deg);} | |
|
255 | .icon-options:before {transform: rotate(90deg);} | |||
254 |
|
256 | |||
255 | // -- END ICON CLASSES -- // |
|
257 | // -- END ICON CLASSES -- // | |
256 |
|
258 |
@@ -131,6 +131,11 b' function setRCMouseBindings(repoName, re' | |||||
131 | window.location = pyroutes.url( |
|
131 | window.location = pyroutes.url( | |
132 | 'edit_repo_perms', {'repo_name': repoName}); |
|
132 | 'edit_repo_perms', {'repo_name': repoName}); | |
133 | }); |
|
133 | }); | |
|
134 | Mousetrap.bind(['t s'], function(e) { | |||
|
135 | if (window.toggleSidebar !== undefined) { | |||
|
136 | window.toggleSidebar(); | |||
|
137 | } | |||
|
138 | }); | |||
134 | } |
|
139 | } | |
135 | } |
|
140 | } | |
136 |
|
141 |
@@ -35,4 +35,75 b' var quick_repo_menu = function() {' | |||||
35 | }, function() { |
|
35 | }, function() { | |
36 | hide_quick_repo_menus(); |
|
36 | hide_quick_repo_menus(); | |
37 | }); |
|
37 | }); | |
38 | }; No newline at end of file |
|
38 | }; | |
|
39 | ||||
|
40 | ||||
|
41 | window.toggleElement = function (elem, target) { | |||
|
42 | var $elem = $(elem); | |||
|
43 | var $target = $(target); | |||
|
44 | ||||
|
45 | if ($target.is(':visible') || $target.length === 0) { | |||
|
46 | $target.hide(); | |||
|
47 | $elem.html($elem.data('toggleOn')) | |||
|
48 | } else { | |||
|
49 | $target.show(); | |||
|
50 | $elem.html($elem.data('toggleOff')) | |||
|
51 | } | |||
|
52 | ||||
|
53 | return false | |||
|
54 | } | |||
|
55 | ||||
|
56 | var marginExpVal = '300' // needs a sync with `.right-sidebar.right-sidebar-expanded` value | |||
|
57 | var marginColVal = '40' // needs a sync with `.right-sidebar.right-sidebar-collapsed` value | |||
|
58 | ||||
|
59 | var marginExpanded = {'margin': '0 {0}px 0 0'.format(marginExpVal)}; | |||
|
60 | var marginCollapsed = {'margin': '0 {0}px 0 0'.format(marginColVal)}; | |||
|
61 | ||||
|
62 | var updateStickyHeader = function () { | |||
|
63 | if (window.updateSticky !== undefined) { | |||
|
64 | // potentially our comments change the active window size, so we | |||
|
65 | // notify sticky elements | |||
|
66 | updateSticky() | |||
|
67 | } | |||
|
68 | } | |||
|
69 | ||||
|
70 | var expandSidebar = function () { | |||
|
71 | var $sideBar = $('.right-sidebar'); | |||
|
72 | $('.outerwrapper').css(marginExpanded); | |||
|
73 | $('.sidebar-toggle a').html('<i class="icon-right" style="margin-right: -10px"></i><i class="icon-right"></i>'); | |||
|
74 | $('.right-sidebar-collapsed-state').hide(); | |||
|
75 | $('.right-sidebar-expanded-state').show(); | |||
|
76 | $('.branding').addClass('display-none'); | |||
|
77 | $sideBar.addClass('right-sidebar-expanded') | |||
|
78 | $sideBar.removeClass('right-sidebar-collapsed') | |||
|
79 | } | |||
|
80 | ||||
|
81 | var collapseSidebar = function () { | |||
|
82 | var $sideBar = $('.right-sidebar'); | |||
|
83 | $('.outerwrapper').css(marginCollapsed); | |||
|
84 | $('.sidebar-toggle a').html('<i class="icon-left" style="margin-right: -10px"></i><i class="icon-left"></i>'); | |||
|
85 | $('.right-sidebar-collapsed-state').show(); | |||
|
86 | $('.right-sidebar-expanded-state').hide(); | |||
|
87 | $('.branding').removeClass('display-none'); | |||
|
88 | $sideBar.removeClass('right-sidebar-expanded') | |||
|
89 | $sideBar.addClass('right-sidebar-collapsed') | |||
|
90 | } | |||
|
91 | ||||
|
92 | window.toggleSidebar = function () { | |||
|
93 | var $sideBar = $('.right-sidebar'); | |||
|
94 | ||||
|
95 | if ($sideBar.hasClass('right-sidebar-expanded')) { | |||
|
96 | // expanded -> collapsed transition | |||
|
97 | collapseSidebar(); | |||
|
98 | var sidebarState = 'collapsed'; | |||
|
99 | ||||
|
100 | } else { | |||
|
101 | // collapsed -> expanded | |||
|
102 | expandSidebar(); | |||
|
103 | var sidebarState = 'expanded'; | |||
|
104 | } | |||
|
105 | ||||
|
106 | // update our other sticky header in same context | |||
|
107 | updateStickyHeader(); | |||
|
108 | storeUserSessionAttr('rc_user_session_attr.sidebarState', sidebarState); | |||
|
109 | } |
@@ -279,8 +279,11 b' ReviewersController = function () {' | |||||
279 | $('#user').show(); // show user autocomplete after load |
|
279 | $('#user').show(); // show user autocomplete after load | |
280 |
|
280 | |||
281 | var commitElements = data["diff_info"]['commits']; |
|
281 | var commitElements = data["diff_info"]['commits']; | |
|
282 | ||||
282 | if (commitElements.length === 0) { |
|
283 | if (commitElements.length === 0) { | |
283 | prButtonLock(true, _gettext('no commits'), 'all'); |
|
284 | var noCommitsMsg = '<span class="alert-text-warning">{0}</span>'.format( | |
|
285 | _gettext('There are no commits to merge.')); | |||
|
286 | prButtonLock(true, noCommitsMsg, 'all'); | |||
284 |
|
287 | |||
285 | } else { |
|
288 | } else { | |
286 | // un-lock PR button, so we cannot send PR before it's calculated |
|
289 | // un-lock PR button, so we cannot send PR before it's calculated | |
@@ -324,7 +327,6 b' ReviewersController = function () {' | |||||
324 | }; |
|
327 | }; | |
325 |
|
328 | |||
326 | this.addReviewMember = function (reviewer_obj, reasons, mandatory) { |
|
329 | this.addReviewMember = function (reviewer_obj, reasons, mandatory) { | |
327 | var members = self.$reviewMembers.get(0); |
|
|||
328 | var id = reviewer_obj.user_id; |
|
330 | var id = reviewer_obj.user_id; | |
329 | var username = reviewer_obj.username; |
|
331 | var username = reviewer_obj.username; | |
330 |
|
332 | |||
@@ -333,10 +335,10 b' ReviewersController = function () {' | |||||
333 |
|
335 | |||
334 | // register IDS to check if we don't have this ID already in |
|
336 | // register IDS to check if we don't have this ID already in | |
335 | var currentIds = []; |
|
337 | var currentIds = []; | |
336 | var _els = self.$reviewMembers.find('li').toArray(); |
|
338 | ||
337 | for (el in _els) { |
|
339 | $.each(self.$reviewMembers.find('.reviewer_entry'), function (index, value) { | |
338 |
currentIds.push( |
|
340 | currentIds.push($(value).data('reviewerUserId')) | |
339 | } |
|
341 | }) | |
340 |
|
342 | |||
341 | var userAllowedReview = function (userId) { |
|
343 | var userAllowedReview = function (userId) { | |
342 | var allowed = true; |
|
344 | var allowed = true; | |
@@ -354,12 +356,12 b' ReviewersController = function () {' | |||||
354 | alert(_gettext('User `{0}` not allowed to be a reviewer').format(username)); |
|
356 | alert(_gettext('User `{0}` not allowed to be a reviewer').format(username)); | |
355 | } else { |
|
357 | } else { | |
356 | // only add if it's not there |
|
358 | // only add if it's not there | |
357 |
var alreadyReviewer = currentIds.indexOf( |
|
359 | var alreadyReviewer = currentIds.indexOf(id) != -1; | |
358 |
|
360 | |||
359 | if (alreadyReviewer) { |
|
361 | if (alreadyReviewer) { | |
360 | alert(_gettext('User `{0}` already in reviewers').format(username)); |
|
362 | alert(_gettext('User `{0}` already in reviewers').format(username)); | |
361 | } else { |
|
363 | } else { | |
362 |
|
|
364 | var reviewerEntry = renderTemplate('reviewMemberEntry', { | |
363 | 'member': reviewer_obj, |
|
365 | 'member': reviewer_obj, | |
364 | 'mandatory': mandatory, |
|
366 | 'mandatory': mandatory, | |
365 | 'reasons': reasons, |
|
367 | 'reasons': reasons, | |
@@ -368,7 +370,9 b' ReviewersController = function () {' | |||||
368 | 'review_status_label': _gettext('Not Reviewed'), |
|
370 | 'review_status_label': _gettext('Not Reviewed'), | |
369 | 'user_group': reviewer_obj.user_group, |
|
371 | 'user_group': reviewer_obj.user_group, | |
370 | 'create': true, |
|
372 | 'create': true, | |
371 | }); |
|
373 | 'rule_show': true, | |
|
374 | }) | |||
|
375 | $(self.$reviewMembers.selector).append(reviewerEntry); | |||
372 | tooltipActivate(); |
|
376 | tooltipActivate(); | |
373 | } |
|
377 | } | |
374 | } |
|
378 | } | |
@@ -492,7 +496,7 b' var ReviewerAutoComplete = function(inpu' | |||||
492 | }; |
|
496 | }; | |
493 |
|
497 | |||
494 |
|
498 | |||
495 | VersionController = function () { |
|
499 | window.VersionController = function () { | |
496 | var self = this; |
|
500 | var self = this; | |
497 | this.$verSource = $('input[name=ver_source]'); |
|
501 | this.$verSource = $('input[name=ver_source]'); | |
498 | this.$verTarget = $('input[name=ver_target]'); |
|
502 | this.$verTarget = $('input[name=ver_target]'); | |
@@ -612,25 +616,10 b' VersionController = function () {' | |||||
612 | return false |
|
616 | return false | |
613 | }; |
|
617 | }; | |
614 |
|
618 | |||
615 | this.toggleElement = function (elem, target) { |
|
|||
616 | var $elem = $(elem); |
|
|||
617 | var $target = $(target); |
|
|||
618 |
|
||||
619 | if ($target.is(':visible') || $target.length === 0) { |
|
|||
620 | $target.hide(); |
|
|||
621 | $elem.html($elem.data('toggleOn')) |
|
|||
622 | } else { |
|
|||
623 | $target.show(); |
|
|||
624 | $elem.html($elem.data('toggleOff')) |
|
|||
625 | } |
|
|||
626 |
|
||||
627 | return false |
|
|||
628 | } |
|
|||
629 |
|
||||
630 | }; |
|
619 | }; | |
631 |
|
620 | |||
632 |
|
621 | |||
633 | UpdatePrController = function () { |
|
622 | window.UpdatePrController = function () { | |
634 | var self = this; |
|
623 | var self = this; | |
635 | this.$updateCommits = $('#update_commits'); |
|
624 | this.$updateCommits = $('#update_commits'); | |
636 | this.$updateCommitsSwitcher = $('#update_commits_switcher'); |
|
625 | this.$updateCommitsSwitcher = $('#update_commits_switcher'); | |
@@ -672,4 +661,230 b' UpdatePrController = function () {' | |||||
672 | templateContext.repo_name, |
|
661 | templateContext.repo_name, | |
673 | templateContext.pull_request_data.pull_request_id, force); |
|
662 | templateContext.pull_request_data.pull_request_id, force); | |
674 | }; |
|
663 | }; | |
675 | }; No newline at end of file |
|
664 | }; | |
|
665 | ||||
|
666 | /** | |||
|
667 | * Reviewer display panel | |||
|
668 | */ | |||
|
669 | window.ReviewersPanel = { | |||
|
670 | editButton: null, | |||
|
671 | closeButton: null, | |||
|
672 | addButton: null, | |||
|
673 | removeButtons: null, | |||
|
674 | reviewRules: null, | |||
|
675 | setReviewers: null, | |||
|
676 | ||||
|
677 | setSelectors: function () { | |||
|
678 | var self = this; | |||
|
679 | self.editButton = $('#open_edit_reviewers'); | |||
|
680 | self.closeButton =$('#close_edit_reviewers'); | |||
|
681 | self.addButton = $('#add_reviewer'); | |||
|
682 | self.removeButtons = $('.reviewer_member_remove,.reviewer_member_mandatory_remove'); | |||
|
683 | }, | |||
|
684 | ||||
|
685 | init: function (reviewRules, setReviewers) { | |||
|
686 | var self = this; | |||
|
687 | self.setSelectors(); | |||
|
688 | ||||
|
689 | this.reviewRules = reviewRules; | |||
|
690 | this.setReviewers = setReviewers; | |||
|
691 | ||||
|
692 | this.editButton.on('click', function (e) { | |||
|
693 | self.edit(); | |||
|
694 | }); | |||
|
695 | this.closeButton.on('click', function (e) { | |||
|
696 | self.close(); | |||
|
697 | self.renderReviewers(); | |||
|
698 | }); | |||
|
699 | ||||
|
700 | self.renderReviewers(); | |||
|
701 | ||||
|
702 | }, | |||
|
703 | ||||
|
704 | renderReviewers: function () { | |||
|
705 | ||||
|
706 | $('#review_members').html('') | |||
|
707 | $.each(this.setReviewers.reviewers, function (key, val) { | |||
|
708 | var member = val; | |||
|
709 | ||||
|
710 | var entry = renderTemplate('reviewMemberEntry', { | |||
|
711 | 'member': member, | |||
|
712 | 'mandatory': member.mandatory, | |||
|
713 | 'reasons': member.reasons, | |||
|
714 | 'allowed_to_update': member.allowed_to_update, | |||
|
715 | 'review_status': member.review_status, | |||
|
716 | 'review_status_label': member.review_status_label, | |||
|
717 | 'user_group': member.user_group, | |||
|
718 | 'create': false | |||
|
719 | }); | |||
|
720 | ||||
|
721 | $('#review_members').append(entry) | |||
|
722 | }); | |||
|
723 | tooltipActivate(); | |||
|
724 | ||||
|
725 | }, | |||
|
726 | ||||
|
727 | edit: function (event) { | |||
|
728 | this.editButton.hide(); | |||
|
729 | this.closeButton.show(); | |||
|
730 | this.addButton.show(); | |||
|
731 | $(this.removeButtons.selector).css('visibility', 'visible'); | |||
|
732 | // review rules | |||
|
733 | reviewersController.loadReviewRules(this.reviewRules); | |||
|
734 | }, | |||
|
735 | ||||
|
736 | close: function (event) { | |||
|
737 | this.editButton.show(); | |||
|
738 | this.closeButton.hide(); | |||
|
739 | this.addButton.hide(); | |||
|
740 | $(this.removeButtons.selector).css('visibility', 'hidden'); | |||
|
741 | // hide review rules | |||
|
742 | reviewersController.hideReviewRules() | |||
|
743 | } | |||
|
744 | }; | |||
|
745 | ||||
|
746 | ||||
|
747 | /** | |||
|
748 | * OnLine presence using channelstream | |||
|
749 | */ | |||
|
750 | window.ReviewerPresenceController = function (channel) { | |||
|
751 | var self = this; | |||
|
752 | this.channel = channel; | |||
|
753 | this.users = {}; | |||
|
754 | ||||
|
755 | this.storeUsers = function (users) { | |||
|
756 | self.users = {} | |||
|
757 | $.each(users, function (index, value) { | |||
|
758 | var userId = value.state.id; | |||
|
759 | self.users[userId] = value.state; | |||
|
760 | }) | |||
|
761 | } | |||
|
762 | ||||
|
763 | this.render = function () { | |||
|
764 | $.each($('.reviewer_entry'), function (index, value) { | |||
|
765 | var userData = $(value).data(); | |||
|
766 | if (self.users[userData.reviewerUserId] !== undefined) { | |||
|
767 | $(value).find('.presence-state').show(); | |||
|
768 | } else { | |||
|
769 | $(value).find('.presence-state').hide(); | |||
|
770 | } | |||
|
771 | }) | |||
|
772 | }; | |||
|
773 | ||||
|
774 | this.handlePresence = function (data) { | |||
|
775 | if (data.type == 'presence' && data.channel === self.channel) { | |||
|
776 | this.storeUsers(data.users); | |||
|
777 | this.render() | |||
|
778 | } | |||
|
779 | }; | |||
|
780 | ||||
|
781 | this.handleChannelUpdate = function (data) { | |||
|
782 | if (data.channel === this.channel) { | |||
|
783 | this.storeUsers(data.state.users); | |||
|
784 | this.render() | |||
|
785 | } | |||
|
786 | ||||
|
787 | }; | |||
|
788 | ||||
|
789 | /* subscribe to the current presence */ | |||
|
790 | $.Topic('/connection_controller/presence').subscribe(this.handlePresence.bind(this)); | |||
|
791 | /* subscribe to updates e.g connect/disconnect */ | |||
|
792 | $.Topic('/connection_controller/channel_update').subscribe(this.handleChannelUpdate.bind(this)); | |||
|
793 | ||||
|
794 | }; | |||
|
795 | ||||
|
796 | window.refreshComments = function (version) { | |||
|
797 | version = version || templateContext.pull_request_data.pull_request_version || ''; | |||
|
798 | ||||
|
799 | // Pull request case | |||
|
800 | if (templateContext.pull_request_data.pull_request_id !== null) { | |||
|
801 | var params = { | |||
|
802 | 'pull_request_id': templateContext.pull_request_data.pull_request_id, | |||
|
803 | 'repo_name': templateContext.repo_name, | |||
|
804 | 'version': version, | |||
|
805 | }; | |||
|
806 | var loadUrl = pyroutes.url('pullrequest_comments', params); | |||
|
807 | } // commit case | |||
|
808 | else { | |||
|
809 | return | |||
|
810 | } | |||
|
811 | ||||
|
812 | var currentIDs = [] | |||
|
813 | $.each($('.comment'), function (idx, element) { | |||
|
814 | currentIDs.push($(element).data('commentId')); | |||
|
815 | }); | |||
|
816 | var data = {"comments[]": currentIDs}; | |||
|
817 | ||||
|
818 | var $targetElem = $('.comments-content-table'); | |||
|
819 | $targetElem.css('opacity', 0.3); | |||
|
820 | $targetElem.load( | |||
|
821 | loadUrl, data, function (responseText, textStatus, jqXHR) { | |||
|
822 | if (jqXHR.status !== 200) { | |||
|
823 | return false; | |||
|
824 | } | |||
|
825 | var $counterElem = $('#comments-count'); | |||
|
826 | var newCount = $(responseText).data('counter'); | |||
|
827 | if (newCount !== undefined) { | |||
|
828 | var callback = function () { | |||
|
829 | $counterElem.animate({'opacity': 1.00}, 200) | |||
|
830 | $counterElem.html(newCount); | |||
|
831 | }; | |||
|
832 | $counterElem.animate({'opacity': 0.15}, 200, callback); | |||
|
833 | } | |||
|
834 | ||||
|
835 | $targetElem.css('opacity', 1); | |||
|
836 | tooltipActivate(); | |||
|
837 | } | |||
|
838 | ); | |||
|
839 | } | |||
|
840 | ||||
|
841 | window.refreshTODOs = function (version) { | |||
|
842 | version = version || templateContext.pull_request_data.pull_request_version || ''; | |||
|
843 | // Pull request case | |||
|
844 | if (templateContext.pull_request_data.pull_request_id !== null) { | |||
|
845 | var params = { | |||
|
846 | 'pull_request_id': templateContext.pull_request_data.pull_request_id, | |||
|
847 | 'repo_name': templateContext.repo_name, | |||
|
848 | 'version': version, | |||
|
849 | }; | |||
|
850 | var loadUrl = pyroutes.url('pullrequest_comments', params); | |||
|
851 | } // commit case | |||
|
852 | else { | |||
|
853 | return | |||
|
854 | } | |||
|
855 | ||||
|
856 | var currentIDs = [] | |||
|
857 | $.each($('.comment'), function (idx, element) { | |||
|
858 | currentIDs.push($(element).data('commentId')); | |||
|
859 | }); | |||
|
860 | ||||
|
861 | var data = {"comments[]": currentIDs}; | |||
|
862 | var $targetElem = $('.todos-content-table'); | |||
|
863 | $targetElem.css('opacity', 0.3); | |||
|
864 | $targetElem.load( | |||
|
865 | loadUrl, data, function (responseText, textStatus, jqXHR) { | |||
|
866 | if (jqXHR.status !== 200) { | |||
|
867 | return false; | |||
|
868 | } | |||
|
869 | var $counterElem = $('#todos-count') | |||
|
870 | var newCount = $(responseText).data('counter'); | |||
|
871 | if (newCount !== undefined) { | |||
|
872 | var callback = function () { | |||
|
873 | $counterElem.animate({'opacity': 1.00}, 200) | |||
|
874 | $counterElem.html(newCount); | |||
|
875 | }; | |||
|
876 | $counterElem.animate({'opacity': 0.15}, 200, callback); | |||
|
877 | } | |||
|
878 | ||||
|
879 | $targetElem.css('opacity', 1); | |||
|
880 | tooltipActivate(); | |||
|
881 | } | |||
|
882 | ); | |||
|
883 | } | |||
|
884 | ||||
|
885 | window.refreshAllComments = function (version) { | |||
|
886 | version = version || templateContext.pull_request_data.pull_request_version || ''; | |||
|
887 | ||||
|
888 | refreshComments(version); | |||
|
889 | refreshTODOs(version); | |||
|
890 | }; |
@@ -701,9 +701,6 b'' | |||||
701 | notice_messages, notice_level = c.rhodecode_user.get_notice_messages() |
|
701 | notice_messages, notice_level = c.rhodecode_user.get_notice_messages() | |
702 | notice_display = 'none' if len(notice_messages) == 0 else '' |
|
702 | notice_display = 'none' if len(notice_messages) == 0 else '' | |
703 | %> |
|
703 | %> | |
704 | <style> |
|
|||
705 |
|
||||
706 | </style> |
|
|||
707 |
|
704 | |||
708 | <ul id="quick" class="main_nav navigation horizontal-list"> |
|
705 | <ul id="quick" class="main_nav navigation horizontal-list"> | |
709 | ## notice box for important system messages |
|
706 | ## notice box for important system messages | |
@@ -1202,6 +1199,7 b'' | |||||
1202 | ('g p', 'Goto pull requests page'), |
|
1199 | ('g p', 'Goto pull requests page'), | |
1203 | ('g o', 'Goto repository settings'), |
|
1200 | ('g o', 'Goto repository settings'), | |
1204 | ('g O', 'Goto repository access permissions settings'), |
|
1201 | ('g O', 'Goto repository access permissions settings'), | |
|
1202 | ('t s', 'Toggle sidebar on some pages'), | |||
1205 | ] |
|
1203 | ] | |
1206 | %> |
|
1204 | %> | |
1207 | %for key, desc in elems: |
|
1205 | %for key, desc in elems: | |
@@ -1221,3 +1219,36 b'' | |||||
1221 | </div><!-- /.modal-content --> |
|
1219 | </div><!-- /.modal-content --> | |
1222 | </div><!-- /.modal-dialog --> |
|
1220 | </div><!-- /.modal-dialog --> | |
1223 | </div><!-- /.modal --> |
|
1221 | </div><!-- /.modal --> | |
|
1222 | ||||
|
1223 | ||||
|
1224 | <script type="text/javascript"> | |||
|
1225 | (function () { | |||
|
1226 | "use sctrict"; | |||
|
1227 | ||||
|
1228 | var $sideBar = $('.right-sidebar'); | |||
|
1229 | var expanded = $sideBar.hasClass('right-sidebar-expanded'); | |||
|
1230 | var sidebarState = templateContext.session_attrs.sidebarState; | |||
|
1231 | var sidebarEnabled = $('aside.right-sidebar').get(0); | |||
|
1232 | ||||
|
1233 | if (sidebarState === 'expanded') { | |||
|
1234 | expanded = true | |||
|
1235 | } else if (sidebarState === 'collapsed') { | |||
|
1236 | expanded = false | |||
|
1237 | } | |||
|
1238 | if (sidebarEnabled) { | |||
|
1239 | // show sidebar since it's hidden on load | |||
|
1240 | $('.right-sidebar').show(); | |||
|
1241 | ||||
|
1242 | // init based on set initial class, or if defined user session attrs | |||
|
1243 | if (expanded) { | |||
|
1244 | window.expandSidebar(); | |||
|
1245 | window.updateStickyHeader(); | |||
|
1246 | ||||
|
1247 | } else { | |||
|
1248 | window.collapseSidebar(); | |||
|
1249 | window.updateStickyHeader(); | |||
|
1250 | } | |||
|
1251 | } | |||
|
1252 | })() | |||
|
1253 | ||||
|
1254 | </script> |
@@ -4,6 +4,8 b'' | |||||
4 | <%namespace name="base" file="/base/base.mako"/> |
|
4 | <%namespace name="base" file="/base/base.mako"/> | |
5 | <%namespace name="diff_block" file="/changeset/diff_block.mako"/> |
|
5 | <%namespace name="diff_block" file="/changeset/diff_block.mako"/> | |
6 | <%namespace name="file_base" file="/files/base.mako"/> |
|
6 | <%namespace name="file_base" file="/files/base.mako"/> | |
|
7 | <%namespace name="sidebar" file="/base/sidebar.mako"/> | |||
|
8 | ||||
7 |
|
9 | |||
8 | <%def name="title()"> |
|
10 | <%def name="title()"> | |
9 | ${_('{} Commit').format(c.repo_name)} - ${h.show_id(c.commit)} |
|
11 | ${_('{} Commit').format(c.repo_name)} - ${h.show_id(c.commit)} | |
@@ -100,22 +102,6 b'' | |||||
100 | % endif |
|
102 | % endif | |
101 | </div> |
|
103 | </div> | |
102 |
|
|
104 | ||
103 | %if c.statuses: |
|
|||
104 | <div class="tag status-tag-${c.statuses[0]} pull-right"> |
|
|||
105 | <i class="icon-circle review-status-${c.statuses[0]}"></i> |
|
|||
106 | <div class="pull-right">${h.commit_status_lbl(c.statuses[0])}</div> |
|
|||
107 | </div> |
|
|||
108 | %endif |
|
|||
109 |
|
||||
110 | </div> |
|
|||
111 |
|
||||
112 | </div> |
|
|||
113 | </div> |
|
|||
114 |
|
||||
115 | <div class="fieldset collapsable-content" data-toggle="summary-details" style="display: none;"> |
|
|||
116 | <div class="left-label-summary"> |
|
|||
117 | <p>${_('Commit navigation')}:</p> |
|
|||
118 | <div class="right-label-summary"> |
|
|||
119 | <span id="parent_link" class="tag tagtag"> |
|
105 | <span id="parent_link" class="tag tagtag"> | |
120 | <a href="#parentCommit" title="${_('Parent Commit')}"><i class="icon-left icon-no-margin"></i>${_('parent')}</a> |
|
106 | <a href="#parentCommit" title="${_('Parent Commit')}"><i class="icon-left icon-no-margin"></i>${_('parent')}</a> | |
121 | </span> |
|
107 | </span> | |
@@ -123,7 +109,9 b'' | |||||
123 | <span id="child_link" class="tag tagtag"> |
|
109 | <span id="child_link" class="tag tagtag"> | |
124 | <a href="#childCommit" title="${_('Child Commit')}">${_('child')}<i class="icon-right icon-no-margin"></i></a> |
|
110 | <a href="#childCommit" title="${_('Child Commit')}">${_('child')}<i class="icon-right icon-no-margin"></i></a> | |
125 | </span> |
|
111 | </span> | |
|
112 | ||||
126 | </div> |
|
113 | </div> | |
|
114 | ||||
127 | </div> |
|
115 | </div> | |
128 | </div> |
|
116 | </div> | |
129 |
|
117 | |||
@@ -160,7 +148,9 b'' | |||||
160 | <%namespace name="cbdiffs" file="/codeblocks/diffs.mako"/> |
|
148 | <%namespace name="cbdiffs" file="/codeblocks/diffs.mako"/> | |
161 | ${cbdiffs.render_diffset_menu(c.changes[c.commit.raw_id], commit=c.commit)} |
|
149 | ${cbdiffs.render_diffset_menu(c.changes[c.commit.raw_id], commit=c.commit)} | |
162 | ${cbdiffs.render_diffset( |
|
150 | ${cbdiffs.render_diffset( | |
163 |
c.changes[c.commit.raw_id], commit=c.commit, use_comments=True, |
|
151 | c.changes[c.commit.raw_id], commit=c.commit, use_comments=True, | |
|
152 | inline_comments=c.inline_comments, | |||
|
153 | show_todos=False)} | |||
164 | </div> |
|
154 | </div> | |
165 |
|
155 | |||
166 | ## template for inline comment form |
|
156 | ## template for inline comment form | |
@@ -169,7 +159,7 b'' | |||||
169 | ## comments heading with count |
|
159 | ## comments heading with count | |
170 | <div class="comments-heading"> |
|
160 | <div class="comments-heading"> | |
171 | <i class="icon-comment"></i> |
|
161 | <i class="icon-comment"></i> | |
172 | ${_('Comments')} ${len(c.comments)} |
|
162 | ${_('General Comments')} ${len(c.comments)} | |
173 | </div> |
|
163 | </div> | |
174 |
|
164 | |||
175 | ## render comments |
|
165 | ## render comments | |
@@ -180,12 +170,130 b'' | |||||
180 | h.commit_status(c.rhodecode_db_repo, c.commit.raw_id))} |
|
170 | h.commit_status(c.rhodecode_db_repo, c.commit.raw_id))} | |
181 | </div> |
|
171 | </div> | |
182 |
|
172 | |||
|
173 | ### NAV SIDEBAR | |||
|
174 | <aside class="right-sidebar right-sidebar-expanded" id="commit-nav-sticky" style="display: none"> | |||
|
175 | <div class="sidenav navbar__inner" > | |||
|
176 | ## TOGGLE | |||
|
177 | <div class="sidebar-toggle" onclick="toggleSidebar(); return false"> | |||
|
178 | <a href="#toggleSidebar" class="grey-link-action"> | |||
|
179 | ||||
|
180 | </a> | |||
|
181 | </div> | |||
|
182 | ||||
|
183 | ## CONTENT | |||
|
184 | <div class="sidebar-content"> | |||
|
185 | ||||
|
186 | ## RULES SUMMARY/RULES | |||
|
187 | <div class="sidebar-element clear-both"> | |||
|
188 | <% vote_title = _ungettext( | |||
|
189 | 'Status calculated based on votes from {} reviewer', | |||
|
190 | 'Status calculated based on votes from {} reviewers', len(c.allowed_reviewers)).format(len(c.allowed_reviewers)) | |||
|
191 | %> | |||
|
192 | ||||
|
193 | <div class="tooltip right-sidebar-collapsed-state" style="display: none" onclick="toggleSidebar(); return false" title="${vote_title}"> | |||
|
194 | <i class="icon-circle review-status-${c.commit_review_status}"></i> | |||
|
195 | ${len(c.allowed_reviewers)} | |||
|
196 | </div> | |||
|
197 | </div> | |||
|
198 | ||||
|
199 | ## REVIEWERS | |||
|
200 | <div class="right-sidebar-expanded-state pr-details-title"> | |||
|
201 | <span class="tooltip sidebar-heading" title="${vote_title}"> | |||
|
202 | <i class="icon-circle review-status-${c.commit_review_status}"></i> | |||
|
203 | ${_('Reviewers')} | |||
|
204 | </span> | |||
|
205 | </div> | |||
|
206 | ||||
|
207 | <div id="reviewers" class="right-sidebar-expanded-state pr-details-content reviewers"> | |||
|
208 | ||||
|
209 | <table id="review_members" class="group_members"> | |||
|
210 | ## This content is loaded via JS and ReviewersPanel | |||
|
211 | </table> | |||
|
212 | ||||
|
213 | </div> | |||
|
214 | ||||
|
215 | ## TODOs | |||
|
216 | <div class="sidebar-element clear-both"> | |||
|
217 | <div class="tooltip right-sidebar-collapsed-state" style="display: none" onclick="toggleSidebar(); return false" title="TODOs"> | |||
|
218 | <i class="icon-flag-filled"></i> | |||
|
219 | <span id="todos-count">${len(c.unresolved_comments)}</span> | |||
|
220 | </div> | |||
|
221 | ||||
|
222 | <div class="right-sidebar-expanded-state pr-details-title"> | |||
|
223 | ## Only show unresolved, that is only what matters | |||
|
224 | <span class="sidebar-heading noselect" onclick="refreshTODOs(); return false"> | |||
|
225 | <i class="icon-flag-filled"></i> | |||
|
226 | TODOs | |||
|
227 | </span> | |||
|
228 | ||||
|
229 | % if c.resolved_comments: | |||
|
230 | <span class="block-right action_button last-item noselect" onclick="$('.unresolved-todo-text').toggle(); return toggleElement(this, '.resolved-todo');" data-toggle-on="Show resolved" data-toggle-off="Hide resolved">Show resolved</span> | |||
|
231 | % else: | |||
|
232 | <span class="block-right last-item noselect">Show resolved</span> | |||
|
233 | % endif | |||
|
234 | ||||
|
235 | </div> | |||
|
236 | ||||
|
237 | <div class="right-sidebar-expanded-state pr-details-content"> | |||
|
238 | % if c.unresolved_comments + c.resolved_comments: | |||
|
239 | ${sidebar.comments_table(c.unresolved_comments + c.resolved_comments, len(c.unresolved_comments), todo_comments=True, is_pr=False)} | |||
|
240 | % else: | |||
|
241 | <table> | |||
|
242 | <tr> | |||
|
243 | <td> | |||
|
244 | ${_('No TODOs yet')} | |||
|
245 | </td> | |||
|
246 | </tr> | |||
|
247 | </table> | |||
|
248 | % endif | |||
|
249 | </div> | |||
|
250 | </div> | |||
|
251 | ||||
|
252 | ## COMMENTS | |||
|
253 | <div class="sidebar-element clear-both"> | |||
|
254 | <div class="tooltip right-sidebar-collapsed-state" style="display: none" onclick="toggleSidebar(); return false" title="${_('Comments')}"> | |||
|
255 | <i class="icon-comment" style="color: #949494"></i> | |||
|
256 | <span id="comments-count">${len(c.inline_comments_flat+c.comments)}</span> | |||
|
257 | <span class="display-none" id="general-comments-count">${len(c.comments)}</span> | |||
|
258 | <span class="display-none" id="inline-comments-count">${len(c.inline_comments_flat)}</span> | |||
|
259 | </div> | |||
|
260 | ||||
|
261 | <div class="right-sidebar-expanded-state pr-details-title"> | |||
|
262 | <span class="sidebar-heading noselect" onclick="refreshComments(); return false"> | |||
|
263 | <i class="icon-comment" style="color: #949494"></i> | |||
|
264 | ${_('Comments')} | |||
|
265 | </span> | |||
|
266 | ||||
|
267 | </div> | |||
|
268 | ||||
|
269 | <div class="right-sidebar-expanded-state pr-details-content"> | |||
|
270 | % if c.inline_comments_flat + c.comments: | |||
|
271 | ${sidebar.comments_table(c.inline_comments_flat + c.comments, len(c.inline_comments_flat+c.comments), is_pr=False)} | |||
|
272 | % else: | |||
|
273 | <table> | |||
|
274 | <tr> | |||
|
275 | <td> | |||
|
276 | ${_('No Comments yet')} | |||
|
277 | </td> | |||
|
278 | </tr> | |||
|
279 | </table> | |||
|
280 | % endif | |||
|
281 | </div> | |||
|
282 | ||||
|
283 | </div> | |||
|
284 | ||||
|
285 | </div> | |||
|
286 | ||||
|
287 | </div> | |||
|
288 | </aside> | |||
|
289 | ||||
183 |
|
|
290 | ## FORM FOR MAKING JS ACTION AS CHANGESET COMMENTS | |
184 |
|
|
291 | <script type="text/javascript"> | |
|
292 | window.setReviewersData = ${c.commit_set_reviewers_data_json | n}; | |||
185 |
|
293 | |||
186 |
|
|
294 | $(document).ready(function () { | |
|
295 | var boxmax = parseInt($('#trimmed_message_box').css('max-height'), 10); | |||
187 |
|
296 | |||
188 | var boxmax = parseInt($('#trimmed_message_box').css('max-height'), 10); |
|
|||
189 |
|
|
297 | if ($('#trimmed_message_box').height() === boxmax) { | |
190 |
|
|
298 | $('#message_expand').show(); | |
191 |
|
|
299 | } | |
@@ -225,9 +333,11 b'' | |||||
225 | } |
|
333 | } | |
226 | if(data.results.length === 1){ |
|
334 | if (data.results.length === 1) { | |
227 | var commit = data.results[0]; |
|
335 | var commit = data.results[0]; | |
228 |
window.location = pyroutes.url('repo_commit', { |
|
336 | window.location = pyroutes.url('repo_commit', { | |
229 | } |
|
337 | 'repo_name': '${c.repo_name}', | |
230 | else if(data.results.length === 2){ |
|
338 | 'commit_id': commit.raw_id | |
|
339 | }); | |||
|
340 | } else if (data.results.length === 2) { | |||
231 | $('#child_link').addClass('disabled'); |
|
341 | $('#child_link').addClass('disabled'); | |
232 | $('#child_link').addClass('double'); |
|
342 | $('#child_link').addClass('double'); | |
233 |
|
343 | |||
@@ -236,13 +346,19 b'' | |||||
236 | .replace('__branch__', data.results[0].branch) |
|
346 | .replace('__branch__', data.results[0].branch) | |
237 | .replace('__rev__','r{0}:{1}'.format(data.results[0].revision, data.results[0].raw_id.substr(0,6))) |
|
347 | .replace('__rev__', 'r{0}:{1}'.format(data.results[0].revision, data.results[0].raw_id.substr(0, 6))) | |
238 | .replace('__title__', data.results[0].message) |
|
348 | .replace('__title__', data.results[0].message) | |
239 |
.replace('__url__', pyroutes.url('repo_commit', { |
|
349 | .replace('__url__', pyroutes.url('repo_commit', { | |
|
350 | 'repo_name': '${c.repo_name}', | |||
|
351 | 'commit_id': data.results[0].raw_id | |||
|
352 | })); | |||
240 | _html +=' | '; |
|
353 | _html += ' | '; | |
241 | _html +='<a title="__title__" href="__url__"><span class="tag branchtag"><i class="icon-code-fork"></i>__branch__</span> __rev__</a> ' |
|
354 | _html += '<a title="__title__" href="__url__"><span class="tag branchtag"><i class="icon-code-fork"></i>__branch__</span> __rev__</a> ' | |
242 | .replace('__branch__', data.results[1].branch) |
|
355 | .replace('__branch__', data.results[1].branch) | |
243 | .replace('__rev__','r{0}:{1}'.format(data.results[1].revision, data.results[1].raw_id.substr(0,6))) |
|
356 | .replace('__rev__', 'r{0}:{1}'.format(data.results[1].revision, data.results[1].raw_id.substr(0, 6))) | |
244 | .replace('__title__', data.results[1].message) |
|
357 | .replace('__title__', data.results[1].message) | |
245 |
.replace('__url__', pyroutes.url('repo_commit', { |
|
358 | .replace('__url__', pyroutes.url('repo_commit', { | |
|
359 | 'repo_name': '${c.repo_name}', | |||
|
360 | 'commit_id': data.results[1].raw_id | |||
|
361 | })); | |||
246 | $('#child_link').html(_html); |
|
362 | $('#child_link').html(_html); | |
247 | } |
|
363 | } | |
248 | } |
|
364 | } | |
@@ -264,9 +380,11 b'' | |||||
264 | } |
|
380 | } | |
265 | if(data.results.length === 1){ |
|
381 | if (data.results.length === 1) { | |
266 | var commit = data.results[0]; |
|
382 | var commit = data.results[0]; | |
267 |
window.location = pyroutes.url('repo_commit', { |
|
383 | window.location = pyroutes.url('repo_commit', { | |
268 | } |
|
384 | 'repo_name': '${c.repo_name}', | |
269 | else if(data.results.length === 2){ |
|
385 | 'commit_id': commit.raw_id | |
|
386 | }); | |||
|
387 | } else if (data.results.length === 2) { | |||
270 | $('#parent_link').addClass('disabled'); |
|
388 | $('#parent_link').addClass('disabled'); | |
271 | $('#parent_link').addClass('double'); |
|
389 | $('#parent_link').addClass('double'); | |
272 |
|
390 | |||
@@ -275,13 +393,19 b'' | |||||
275 | .replace('__branch__', data.results[0].branch) |
|
393 | .replace('__branch__', data.results[0].branch) | |
276 | .replace('__rev__','r{0}:{1}'.format(data.results[0].revision, data.results[0].raw_id.substr(0,6))) |
|
394 | .replace('__rev__', 'r{0}:{1}'.format(data.results[0].revision, data.results[0].raw_id.substr(0, 6))) | |
277 | .replace('__title__', data.results[0].message) |
|
395 | .replace('__title__', data.results[0].message) | |
278 |
.replace('__url__', pyroutes.url('repo_commit', { |
|
396 | .replace('__url__', pyroutes.url('repo_commit', { | |
|
397 | 'repo_name': '${c.repo_name}', | |||
|
398 | 'commit_id': data.results[0].raw_id | |||
|
399 | })); | |||
279 | _html +=' | '; |
|
400 | _html += ' | '; | |
280 | _html +='<a title="__title__" href="__url__"><span class="tag branchtag"><i class="icon-code-fork"></i>__branch__</span> __rev__</a>' |
|
401 | _html += '<a title="__title__" href="__url__"><span class="tag branchtag"><i class="icon-code-fork"></i>__branch__</span> __rev__</a>' | |
281 | .replace('__branch__', data.results[1].branch) |
|
402 | .replace('__branch__', data.results[1].branch) | |
282 | .replace('__rev__','r{0}:{1}'.format(data.results[1].revision, data.results[1].raw_id.substr(0,6))) |
|
403 | .replace('__rev__', 'r{0}:{1}'.format(data.results[1].revision, data.results[1].raw_id.substr(0, 6))) | |
283 | .replace('__title__', data.results[1].message) |
|
404 | .replace('__title__', data.results[1].message) | |
284 |
.replace('__url__', pyroutes.url('repo_commit', { |
|
405 | .replace('__url__', pyroutes.url('repo_commit', { | |
|
406 | 'repo_name': '${c.repo_name}', | |||
|
407 | 'commit_id': data.results[1].raw_id | |||
|
408 | })); | |||
285 | $('#parent_link').html(_html); |
|
409 | $('#parent_link').html(_html); | |
286 | } |
|
410 | } | |
287 | } |
|
411 | } | |
@@ -296,6 +420,11 b'' | |||||
296 |
|
|
420 | e.preventDefault(); | |
297 |
|
|
421 | }); | |
298 |
|
422 | |||
|
423 | ReviewersPanel.init(null, setReviewersData); | |||
|
424 | ||||
|
425 | var channel = '${c.commit_broadcast_channel}'; | |||
|
426 | new ReviewerPresenceController(channel) | |||
|
427 | ||||
299 |
|
|
428 | }) | |
300 |
|
|
429 | </script> | |
301 |
|
430 |
@@ -11,6 +11,10 b'' | |||||
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 | <% | |||
|
15 | from rhodecode.model.comment import CommentsModel | |||
|
16 | comment_model = CommentsModel() | |||
|
17 | %> | |||
14 | <% comment_ver = comment.get_index_version(getattr(c, 'versions', [])) %> |
|
18 | <% comment_ver = comment.get_index_version(getattr(c, 'versions', [])) %> | |
15 | <% latest_ver = len(getattr(c, 'versions', [])) %> |
|
19 | <% latest_ver = len(getattr(c, 'versions', [])) %> | |
16 |
|
20 | |||
@@ -155,20 +159,16 b'' | |||||
155 | </div> |
|
159 | </div> | |
156 | %endif |
|
160 | %endif | |
157 |
|
161 | |||
158 | <a class="permalink" href="#comment-${comment.comment_id}">¶ #${comment.comment_id}</a> |
|
|||
159 |
|
||||
160 | <div class="comment-links-block"> |
|
162 | <div class="comment-links-block"> | |
161 |
|
163 | |||
162 | % if inline: |
|
164 | % if inline: | |
163 | <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))}"> | |
164 | % if outdated_at_ver: |
|
166 | % if outdated_at_ver: | |
165 | <code class="tooltip pr-version-num" title="${_('Outdated comment from pull request version v{0}, latest v{1}').format(comment_ver, latest_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> | |
166 | outdated ${'v{}'.format(comment_ver)} | |
|
168 | <code class="action-divider">|</code> | |
167 | </code> |
|
|||
168 | % elif comment_ver: |
|
169 | % elif comment_ver: | |
169 | <code class="tooltip pr-version-num" title="${_('Comment from pull request version v{0}, latest v{1}').format(comment_ver, latest_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 | ${'v{}'.format(comment_ver)} | |
|
171 | <code class="action-divider">|</code> | |
171 | </code> |
|
|||
172 | % endif |
|
172 | % endif | |
173 | </a> |
|
173 | </a> | |
174 | % else: |
|
174 | % else: | |
@@ -179,45 +179,70 b'' | |||||
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 | % else: |
|
184 | % else: | |
184 | <a class="tooltip pr-version" |
|
185 | <a class="tooltip pr-version" | |
185 | 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)}" | |
186 | 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)}" | |
187 | > |
|
188 | > | |
188 | <code class="pr-version-num"> |
|
189 | <code class="pr-version-num">${'v{}'.format(comment_ver)}</code> | |
189 | ${'v{}'.format(comment_ver)} |
|
190 | </a> | |
190 | </code> |
|
191 | <code class="action-divider">|</code> | |
191 | </a> | |
|
|||
192 | % endif |
|
192 | % endif | |
193 |
|
193 | |||
194 | % endif |
|
194 | % endif | |
195 | % endif |
|
195 | % endif | |
196 |
|
|
196 | ||
|
197 | <details class="details-reset details-inline-block"> | |||
|
198 | <summary class="noselect"><i class="icon-options cursor-pointer"></i></summary> | |||
|
199 | <details-menu class="details-dropdown"> | |||
|
200 | ||||
|
201 | <div class="dropdown-item"> | |||
|
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> | |||
|
204 | </div> | |||
|
205 | ||||
197 | ## 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 | |
198 | ## 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 | |
199 | %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())): | |
200 | ## permissions to delete |
|
209 | ## permissions to delete | |
201 | %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): | |
202 | <a onclick="return Rhodecode.comments.editComment(this);" |
|
211 | <div class="dropdown-divider"></div> | |
203 |
|
|
212 | <div class="dropdown-item"> | |
204 |
|
|
213 | <a onclick="return Rhodecode.comments.editComment(this);" class="btn btn-link btn-sm edit-comment">${_('Edit')}</a> | |
205 | class="delete-comment">${_('Delete')}</a> |
|
214 | </div> | |
|
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> | |||
|
217 | </div> | |||
206 | %else: |
|
218 | %else: | |
|
219 | <div class="dropdown-divider"></div> | |||
|
220 | <div class="dropdown-item"> | |||
207 | <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> | |
208 | | <a class="tooltip edit-comment link-disabled" disabled="disabled" title="${_('Action unavailable')}">${_('Delete')}</a> |
|
222 | </div> | |
|
223 | <div class="dropdown-item"> | |||
|
224 | <a class="tooltip edit-comment link-disabled" disabled="disabled" title="${_('Action unavailable')}">${_('Delete')}</a> | |||
|
225 | </div> | |||
209 | %endif |
|
226 | %endif | |
210 | %else: |
|
227 | %else: | |
|
228 | <div class="dropdown-divider"></div> | |||
|
229 | <div class="dropdown-item"> | |||
211 | <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> | |
212 | | <a class="tooltip edit-comment link-disabled" disabled="disabled" title="${_('Action unavailable')}">${_('Delete')}</a> |
|
231 | </div> | |
|
232 | <div class="dropdown-item"> | |||
|
233 | <a class="tooltip edit-comment link-disabled" disabled="disabled" title="${_('Action unavailable')}">${_('Delete')}</a> | |||
|
234 | </div> | |||
213 | %endif |
|
235 | %endif | |
|
236 | </details-menu> | |||
|
237 | </details> | |||
214 |
|
|
238 | ||
|
239 | <code class="action-divider">|</code> | |||
215 | % if outdated_at_ver: |
|
240 | % if outdated_at_ver: | |
216 |
|
|
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> | |
217 |
|
|
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> | |
218 | % else: |
|
243 | % else: | |
219 |
|
|
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> | |
220 |
|
|
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> | |
221 | % endif |
|
246 | % endif | |
222 |
|
247 | |||
223 | </div> |
|
248 | </div> |
@@ -102,6 +102,11 b'' | |||||
102 | <%namespace name="diff_block" file="/changeset/diff_block.mako"/> |
|
102 | <%namespace name="diff_block" file="/changeset/diff_block.mako"/> | |
103 |
|
103 | |||
104 | %for commit in c.commit_ranges: |
|
104 | %for commit in c.commit_ranges: | |
|
105 | ## commit range header for each individual diff | |||
|
106 | <h3> | |||
|
107 | <a class="tooltip revision" title="${h.tooltip(commit.message)}" href="${h.route_path('repo_commit',repo_name=c.repo_name,commit_id=commit.raw_id)}">${('r%s:%s' % (commit.idx,h.short_id(commit.raw_id)))}</a> | |||
|
108 | </h3> | |||
|
109 | ||||
105 | ${cbdiffs.render_diffset_menu(c.changes[commit.raw_id])} |
|
110 | ${cbdiffs.render_diffset_menu(c.changes[commit.raw_id])} | |
106 | ${cbdiffs.render_diffset( |
|
111 | ${cbdiffs.render_diffset( | |
107 | diffset=c.changes[commit.raw_id], |
|
112 | diffset=c.changes[commit.raw_id], |
@@ -61,6 +61,8 b" return '%s_%s_%i' % (h.md5_safe(commit+f" | |||||
61 | diffset_container_id = h.md5(diffset.target_ref) |
|
61 | diffset_container_id = h.md5(diffset.target_ref) | |
62 | collapse_all = len(diffset.files) > collapse_when_files_over |
|
62 | collapse_all = len(diffset.files) > collapse_when_files_over | |
63 | active_pattern_entries = h.get_active_pattern_entries(getattr(c, 'repo_name', None)) |
|
63 | active_pattern_entries = h.get_active_pattern_entries(getattr(c, 'repo_name', None)) | |
|
64 | from rhodecode.lib.diffs import NEW_FILENODE, DEL_FILENODE, \ | |||
|
65 | MOD_FILENODE, RENAMED_FILENODE, CHMOD_FILENODE, BIN_FILENODE, COPIED_FILENODE | |||
64 | %> |
|
66 | %> | |
65 |
|
67 | |||
66 | %if use_comments: |
|
68 | %if use_comments: | |
@@ -208,13 +210,6 b" return '%s_%s_%i' % (h.md5_safe(commit+f" | |||||
208 | <a href="${h.current_route_path(request, fulldiff=1)}" onclick="return confirm('${_("Showing a big diff might take some time and resources, continue?")}')">${_('Show full diff')}</a> |
|
210 | <a href="${h.current_route_path(request, fulldiff=1)}" onclick="return confirm('${_("Showing a big diff might take some time and resources, continue?")}')">${_('Show full diff')}</a> | |
209 | </h2> |
|
211 | </h2> | |
210 | </div> |
|
212 | </div> | |
211 | ## commit range header for each individual diff |
|
|||
212 | % elif commit and hasattr(c, 'commit_ranges') and len(c.commit_ranges) > 1: |
|
|||
213 | <div class="diffset-heading ${(diffset.limited_diff and 'diffset-heading-warning' or '')}"> |
|
|||
214 | <div class="clearinner"> |
|
|||
215 | <a class="tooltip revision" title="${h.tooltip(commit.message)}" href="${h.route_path('repo_commit',repo_name=diffset.repo_name,commit_id=commit.raw_id)}">${('r%s:%s' % (commit.idx,h.short_id(commit.raw_id)))}</a> |
|
|||
216 | </div> |
|
|||
217 | </div> |
|
|||
218 | % endif |
|
213 | % endif | |
219 |
|
214 | |||
220 | <div id="todo-box"> |
|
215 | <div id="todo-box"> | |
@@ -239,6 +234,43 b" return '%s_%s_%i' % (h.md5_safe(commit+f" | |||||
239 | <% over_lines_changed_limit = False %> |
|
234 | <% over_lines_changed_limit = False %> | |
240 | %for i, filediff in enumerate(diffset.files): |
|
235 | %for i, filediff in enumerate(diffset.files): | |
241 |
|
236 | |||
|
237 | %if filediff.source_file_path and filediff.target_file_path: | |||
|
238 | %if filediff.source_file_path != filediff.target_file_path: | |||
|
239 | ## file was renamed, or copied | |||
|
240 | %if RENAMED_FILENODE in filediff.patch['stats']['ops']: | |||
|
241 | <% | |||
|
242 | final_file_name = h.literal(u'{} <i class="icon-angle-left"></i> <del>{}</del>'.format(filediff.target_file_path, filediff.source_file_path)) | |||
|
243 | final_path = filediff.target_file_path | |||
|
244 | %> | |||
|
245 | %elif COPIED_FILENODE in filediff.patch['stats']['ops']: | |||
|
246 | <% | |||
|
247 | final_file_name = h.literal(u'{} <i class="icon-angle-left"></i> {}'.format(filediff.target_file_path, filediff.source_file_path)) | |||
|
248 | final_path = filediff.target_file_path | |||
|
249 | %> | |||
|
250 | %endif | |||
|
251 | %else: | |||
|
252 | ## file was modified | |||
|
253 | <% | |||
|
254 | final_file_name = filediff.source_file_path | |||
|
255 | final_path = final_file_name | |||
|
256 | %> | |||
|
257 | %endif | |||
|
258 | %else: | |||
|
259 | %if filediff.source_file_path: | |||
|
260 | ## file was deleted | |||
|
261 | <% | |||
|
262 | final_file_name = filediff.source_file_path | |||
|
263 | final_path = final_file_name | |||
|
264 | %> | |||
|
265 | %else: | |||
|
266 | ## file was added | |||
|
267 | <% | |||
|
268 | final_file_name = filediff.target_file_path | |||
|
269 | final_path = final_file_name | |||
|
270 | %> | |||
|
271 | %endif | |||
|
272 | %endif | |||
|
273 | ||||
242 | <% |
|
274 | <% | |
243 | lines_changed = filediff.patch['stats']['added'] + filediff.patch['stats']['deleted'] |
|
275 | lines_changed = filediff.patch['stats']['added'] + filediff.patch['stats']['deleted'] | |
244 | over_lines_changed_limit = lines_changed > lines_changed_limit |
|
276 | over_lines_changed_limit = lines_changed > lines_changed_limit | |
@@ -258,13 +290,39 b" return '%s_%s_%i' % (h.md5_safe(commit+f" | |||||
258 | total_file_comments = [_c for _c in h.itertools.chain.from_iterable(file_comments) if not _c.outdated] |
|
290 | total_file_comments = [_c for _c in h.itertools.chain.from_iterable(file_comments) if not _c.outdated] | |
259 | %> |
|
291 | %> | |
260 | <div class="filediff-collapse-indicator icon-"></div> |
|
292 | <div class="filediff-collapse-indicator icon-"></div> | |
|
293 | ||||
|
294 | ## Comments/Options PILL | |||
261 |
<span class="pill-group pull-right" |
|
295 | <span class="pill-group pull-right"> | |
262 | <span class="pill" op="comments"> |
|
296 | <span class="pill" op="comments"> | |
263 |
|
||||
264 | <i class="icon-comment"></i> ${len(total_file_comments)} |
|
297 | <i class="icon-comment"></i> ${len(total_file_comments)} | |
265 | </span> |
|
298 | </span> | |
|
299 | ||||
|
300 | <details class="details-reset details-inline-block"> | |||
|
301 | <summary class="noselect"> | |||
|
302 | <i class="pill icon-options cursor-pointer" op="options"></i> | |||
|
303 | </summary> | |||
|
304 | <details-menu class="details-dropdown"> | |||
|
305 | ||||
|
306 | <div class="dropdown-item"> | |||
|
307 | <span>${final_path}</span> | |||
|
308 | <span class="pull-right icon-clipboard clipboard-action" data-clipboard-text="${final_path}" title="Copy file path"></span> | |||
|
309 | </div> | |||
|
310 | ||||
|
311 | <div class="dropdown-divider"></div> | |||
|
312 | ||||
|
313 | <div class="dropdown-item"> | |||
|
314 | <% permalink = request.current_route_url(_anchor='a_{}'.format(h.FID(filediff.raw_id, filediff.patch['filename']))) %> | |||
|
315 | <a href="${permalink}">ΒΆ permalink</a> | |||
|
316 | <span class="pull-right icon-clipboard clipboard-action" data-clipboard-text="${permalink}" title="Copy permalink"></span> | |||
|
317 | </div> | |||
|
318 | ||||
|
319 | ||||
|
320 | </details-menu> | |||
|
321 | </details> | |||
|
322 | ||||
266 | </span> |
|
323 | </span> | |
267 | ${diff_ops(filediff)} |
|
324 | ||
|
325 | ${diff_ops(final_file_name, filediff)} | |||
268 |
|
326 | |||
269 | </label> |
|
327 | </label> | |
270 |
|
328 | |||
@@ -463,43 +521,15 b" return '%s_%s_%i' % (h.md5_safe(commit+f" | |||||
463 | </div> |
|
521 | </div> | |
464 | </%def> |
|
522 | </%def> | |
465 |
|
523 | |||
466 | <%def name="diff_ops(filediff)"> |
|
524 | <%def name="diff_ops(file_name, filediff)"> | |
467 | <% |
|
525 | <% | |
468 | from rhodecode.lib.diffs import NEW_FILENODE, DEL_FILENODE, \ |
|
526 | from rhodecode.lib.diffs import NEW_FILENODE, DEL_FILENODE, \ | |
469 | MOD_FILENODE, RENAMED_FILENODE, CHMOD_FILENODE, BIN_FILENODE, COPIED_FILENODE |
|
527 | MOD_FILENODE, RENAMED_FILENODE, CHMOD_FILENODE, BIN_FILENODE, COPIED_FILENODE | |
470 | %> |
|
528 | %> | |
471 | <span class="pill"> |
|
529 | <span class="pill"> | |
472 | <i class="icon-file-text"></i> |
|
530 | <i class="icon-file-text"></i> | |
473 | %if filediff.source_file_path and filediff.target_file_path: |
|
531 | ${file_name} | |
474 | %if filediff.source_file_path != filediff.target_file_path: |
|
|||
475 | ## file was renamed, or copied |
|
|||
476 | %if RENAMED_FILENODE in filediff.patch['stats']['ops']: |
|
|||
477 | ${filediff.target_file_path} β¬ <del>${filediff.source_file_path}</del> |
|
|||
478 | <% final_path = filediff.target_file_path %> |
|
|||
479 | %elif COPIED_FILENODE in filediff.patch['stats']['ops']: |
|
|||
480 | ${filediff.target_file_path} β¬ ${filediff.source_file_path} |
|
|||
481 | <% final_path = filediff.target_file_path %> |
|
|||
482 | %endif |
|
|||
483 | %else: |
|
|||
484 | ## file was modified |
|
|||
485 | ${filediff.source_file_path} |
|
|||
486 | <% final_path = filediff.source_file_path %> |
|
|||
487 | %endif |
|
|||
488 | %else: |
|
|||
489 | %if filediff.source_file_path: |
|
|||
490 | ## file was deleted |
|
|||
491 | ${filediff.source_file_path} |
|
|||
492 | <% final_path = filediff.source_file_path %> |
|
|||
493 | %else: |
|
|||
494 | ## file was added |
|
|||
495 | ${filediff.target_file_path} |
|
|||
496 | <% final_path = filediff.target_file_path %> |
|
|||
497 | %endif |
|
|||
498 | %endif |
|
|||
499 | <i style="color: #aaa" class="on-hover-icon icon-clipboard clipboard-action" data-clipboard-text="${final_path}" title="${_('Copy file path')}" onclick="return false;"></i> |
|
|||
500 | </span> |
|
532 | </span> | |
501 | ## anchor link |
|
|||
502 | <a class="pill filediff-anchor" href="#a_${h.FID(filediff.raw_id, filediff.patch['filename'])}">ΒΆ</a> |
|
|||
503 |
|
533 | |||
504 | <span class="pill-group pull-right"> |
|
534 | <span class="pill-group pull-right"> | |
505 |
|
535 |
@@ -53,6 +53,14 b" var data_hovercard_url = pyroutes.url('h" | |||||
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; | |||
|
57 | ||||
|
58 | if (rule_show) { | |||
|
59 | var rule_visibility = 'table-cell'; | |||
|
60 | } else { | |||
|
61 | var rule_visibility = 'none'; | |||
|
62 | } | |||
|
63 | ||||
56 | %> |
|
64 | %> | |
57 |
|
65 | |||
58 | <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 %>"> | |
@@ -98,9 +106,9 b" var data_hovercard_url = pyroutes.url('h" | |||||
98 | </td> |
|
106 | </td> | |
99 |
|
107 | |||
100 | <% } else { %> |
|
108 | <% } else { %> | |
101 | <td> |
|
109 | <td style="text-align: right;width: 10px;"> | |
102 | <% if (allowed_to_update) { %> |
|
110 | <% if (allowed_to_update) { %> | |
103 |
<div class="reviewer_member_remove |
|
111 | <div class="reviewer_member_remove" onclick="reviewersController.removeReviewMember(<%= member.user_id %>, true)" style="visibility: <%= edit_visibility %>;"> | |
104 | <i class="icon-remove"></i> |
|
112 | <i class="icon-remove"></i> | |
105 | </div> |
|
113 | </div> | |
106 | <% } %> |
|
114 | <% } %> | |
@@ -110,7 +118,7 b" var data_hovercard_url = pyroutes.url('h" | |||||
110 | </tr> |
|
118 | </tr> | |
111 |
|
119 | |||
112 | <tr> |
|
120 | <tr> | |
113 |
<td colspan="4" style="display: |
|
121 | <td colspan="4" style="display: <%= rule_visibility %>" class="pr-user-rule-container"> | |
114 | <input type="hidden" name="__start__" value="reviewer:mapping"> |
|
122 | <input type="hidden" name="__start__" value="reviewer:mapping"> | |
115 |
|
123 | |||
116 | <%if (member.user_group && member.user_group.vote_rule) { %> |
|
124 | <%if (member.user_group && member.user_group.vote_rule) { %> |
@@ -19,20 +19,73 b'' | |||||
19 | <div class="box"> |
|
19 | <div class="box"> | |
20 | ${h.secure_form(h.route_path('pullrequest_create', repo_name=c.repo_name, _query=request.GET.mixed()), id='pull_request_form', request=request)} |
|
20 | ${h.secure_form(h.route_path('pullrequest_create', repo_name=c.repo_name, _query=request.GET.mixed()), id='pull_request_form', request=request)} | |
21 |
|
21 | |||
22 |
<div class="box |
|
22 | <div class="box"> | |
23 |
|
23 | |||
24 | <div class="summary-details block-left"> |
|
24 | <div class="summary-details block-left"> | |
25 |
|
25 | |||
26 |
|
||||
27 | <div class="pr-details-title"> |
|
|||
28 | ${_('New pull request')} |
|
|||
29 | </div> |
|
|||
30 |
|
||||
31 | <div class="form" style="padding-top: 10px"> |
|
26 | <div class="form" style="padding-top: 10px"> | |
32 | <!-- fields --> |
|
|||
33 |
|
27 | |||
34 | <div class="fields" > |
|
28 | <div class="fields" > | |
35 |
|
29 | |||
|
30 | ## COMMIT FLOW | |||
|
31 | <div class="field"> | |||
|
32 | <div class="label label-textarea"> | |||
|
33 | <label for="commit_flow">${_('Commit flow')}:</label> | |||
|
34 | </div> | |||
|
35 | ||||
|
36 | <div class="content"> | |||
|
37 | <div class="flex-container"> | |||
|
38 | <div style="width: 45%;"> | |||
|
39 | <div class="panel panel-default source-panel"> | |||
|
40 | <div class="panel-heading"> | |||
|
41 | <h3 class="panel-title">${_('Source repository')}</h3> | |||
|
42 | </div> | |||
|
43 | <div class="panel-body"> | |||
|
44 | <div style="display:none">${c.rhodecode_db_repo.description}</div> | |||
|
45 | ${h.hidden('source_repo')} | |||
|
46 | ${h.hidden('source_ref')} | |||
|
47 | ||||
|
48 | <div id="pr_open_message"></div> | |||
|
49 | </div> | |||
|
50 | </div> | |||
|
51 | </div> | |||
|
52 | ||||
|
53 | <div style="width: 90px; text-align: center; padding-top: 30px"> | |||
|
54 | <div> | |||
|
55 | <i class="icon-right" style="font-size: 2.2em"></i> | |||
|
56 | </div> | |||
|
57 | <div style="position: relative; top: 10px"> | |||
|
58 | <span class="tag tag"> | |||
|
59 | <span id="switch_base"></span> | |||
|
60 | </span> | |||
|
61 | </div> | |||
|
62 | ||||
|
63 | </div> | |||
|
64 | ||||
|
65 | <div style="width: 45%;"> | |||
|
66 | ||||
|
67 | <div class="panel panel-default target-panel"> | |||
|
68 | <div class="panel-heading"> | |||
|
69 | <h3 class="panel-title">${_('Target repository')}</h3> | |||
|
70 | </div> | |||
|
71 | <div class="panel-body"> | |||
|
72 | <div style="display:none" id="target_repo_desc"></div> | |||
|
73 | ${h.hidden('target_repo')} | |||
|
74 | ${h.hidden('target_ref')} | |||
|
75 | <span id="target_ref_loading" style="display: none"> | |||
|
76 | ${_('Loading refs...')} | |||
|
77 | </span> | |||
|
78 | </div> | |||
|
79 | </div> | |||
|
80 | ||||
|
81 | </div> | |||
|
82 | </div> | |||
|
83 | ||||
|
84 | </div> | |||
|
85 | ||||
|
86 | </div> | |||
|
87 | ||||
|
88 | ## TITLE | |||
36 |
|
|
89 | <div class="field"> | |
37 | <div class="label"> |
|
90 | <div class="label"> | |
38 | <label for="pullrequest_title">${_('Title')}:</label> |
|
91 | <label for="pullrequest_title">${_('Title')}:</label> | |
@@ -45,6 +98,7 b'' | |||||
45 | </p> |
|
98 | </p> | |
46 |
|
|
99 | </div> | |
47 |
|
100 | |||
|
101 | ## DESC | |||
48 | <div class="field"> |
|
102 | <div class="field"> | |
49 | <div class="label label-textarea"> |
|
103 | <div class="label label-textarea"> | |
50 | <label for="pullrequest_desc">${_('Description')}:</label> |
|
104 | <label for="pullrequest_desc">${_('Description')}:</label> | |
@@ -55,72 +109,14 b'' | |||||
55 | </div> |
|
109 | </div> | |
56 | </div> |
|
110 | </div> | |
57 |
|
111 | |||
|
112 | ## REVIEWERS | |||
58 | <div class="field"> |
|
113 | <div class="field"> | |
59 | <div class="label label-textarea"> |
|
114 | <div class="label label-textarea"> | |
60 |
<label for=" |
|
115 | <label for="pullrequest_reviewers">${_('Reviewers')}:</label> | |
61 | </div> |
|
|||
62 |
|
||||
63 | ## TODO: johbo: Abusing the "content" class here to get the |
|
|||
64 | ## desired effect. Should be replaced by a proper solution. |
|
|||
65 |
|
||||
66 | ##ORG |
|
|||
67 | <div class="content"> |
|
|||
68 | <strong>${_('Source repository')}:</strong> |
|
|||
69 | ${c.rhodecode_db_repo.description} |
|
|||
70 | </div> |
|
116 | </div> | |
71 | <div class="content"> |
|
117 | <div class="content"> | |
72 | ${h.hidden('source_repo')} |
|
|||
73 | ${h.hidden('source_ref')} |
|
|||
74 | </div> |
|
|||
75 |
|
||||
76 | ##OTHER, most Probably the PARENT OF THIS FORK |
|
|||
77 | <div class="content"> |
|
|||
78 | ## filled with JS |
|
|||
79 | <div id="target_repo_desc"></div> |
|
|||
80 | </div> |
|
|||
81 |
|
||||
82 | <div class="content"> |
|
|||
83 | ${h.hidden('target_repo')} |
|
|||
84 | ${h.hidden('target_ref')} |
|
|||
85 | <span id="target_ref_loading" style="display: none"> |
|
|||
86 | ${_('Loading refs...')} |
|
|||
87 | </span> |
|
|||
88 | </div> |
|
|||
89 | </div> |
|
|||
90 |
|
||||
91 | <div class="field"> |
|
|||
92 | <div class="label label-textarea"> |
|
|||
93 | <label for="pullrequest_submit"></label> |
|
|||
94 | </div> |
|
|||
95 | <div class="input"> |
|
|||
96 | <div class="pr-submit-button"> |
|
|||
97 | <input id="pr_submit" class="btn" name="save" type="submit" value="${_('Submit Pull Request')}"> |
|
|||
98 | </div> |
|
|||
99 | <div id="pr_open_message"></div> |
|
|||
100 | </div> |
|
|||
101 | </div> |
|
|||
102 |
|
||||
103 | <div class="pr-spacing-container"></div> |
|
|||
104 | </div> |
|
|||
105 | </div> |
|
|||
106 | </div> |
|
|||
107 | <div> |
|
|||
108 | ## AUTHOR |
|
|||
109 | <div class="reviewers-title block-right"> |
|
|||
110 | <div class="pr-details-title"> |
|
|||
111 | ${_('Author of this pull request')} |
|
|||
112 | </div> |
|
|||
113 | </div> |
|
|||
114 | <div class="block-right pr-details-content reviewers"> |
|
|||
115 | <ul class="group_members"> |
|
|||
116 | <li> |
|
|||
117 | ${self.gravatar_with_user(c.rhodecode_user.email, 16, tooltip=True)} |
|
|||
118 | </li> |
|
|||
119 | </ul> |
|
|||
120 | </div> |
|
|||
121 |
|
||||
122 | ## REVIEW RULES |
|
118 | ## REVIEW RULES | |
123 |
<div id="review_rules" style="display: none" class="reviewers-title |
|
119 | <div id="review_rules" style="display: none" class="reviewers-title"> | |
124 | <div class="pr-details-title"> |
|
120 | <div class="pr-details-title"> | |
125 | ${_('Reviewer rules')} |
|
121 | ${_('Reviewer rules')} | |
126 | </div> |
|
122 | </div> | |
@@ -130,32 +126,48 b'' | |||||
130 | </div> |
|
126 | </div> | |
131 |
|
127 | |||
132 | ## REVIEWERS |
|
128 | ## REVIEWERS | |
133 |
<div class="reviewers-title |
|
129 | <div class="reviewers-title"> | |
134 | <div class="pr-details-title"> |
|
130 | <div class="pr-details-title"> | |
135 | ${_('Pull request reviewers')} |
|
131 | ${_('Pull request reviewers')} | |
136 | <span class="calculate-reviewers"> - ${_('loading...')}</span> |
|
132 | <span class="calculate-reviewers"> - ${_('loading...')}</span> | |
137 | </div> |
|
133 | </div> | |
138 | </div> |
|
134 | </div> | |
139 |
<div id="reviewers" class=" |
|
135 | <div id="reviewers" class="pr-details-content reviewers"> | |
140 | ## members goes here, filled via JS based on initial selection ! |
|
136 | ## members goes here, filled via JS based on initial selection ! | |
141 | <input type="hidden" name="__start__" value="review_members:sequence"> |
|
137 | <input type="hidden" name="__start__" value="review_members:sequence"> | |
142 |
< |
|
138 | <table id="review_members" class="group_members"> | |
|
139 | ## This content is loaded via JS and ReviewersPanel | |||
|
140 | </table> | |||
143 | <input type="hidden" name="__end__" value="review_members:sequence"> |
|
141 | <input type="hidden" name="__end__" value="review_members:sequence"> | |
|
142 | ||||
144 | <div id="add_reviewer_input" class='ac'> |
|
143 | <div id="add_reviewer_input" class='ac'> | |
145 | <div class="reviewer_ac"> |
|
144 | <div class="reviewer_ac"> | |
146 | ${h.text('user', class_='ac-input', placeholder=_('Add reviewer or reviewer group'))} |
|
145 | ${h.text('user', class_='ac-input', placeholder=_('Add reviewer or reviewer group'))} | |
147 | <div id="reviewers_container"></div> |
|
146 | <div id="reviewers_container"></div> | |
148 | </div> |
|
147 | </div> | |
149 | </div> |
|
148 | </div> | |
|
149 | ||||
150 | </div> |
|
150 | </div> | |
151 | </div> |
|
151 | </div> | |
152 | </div> |
|
152 | </div> | |
153 | <div class="box"> |
|
153 | ||
154 | <div> |
|
154 | ## SUBMIT | |
155 | ## overview pulled by ajax |
|
155 | <div class="field"> | |
156 | <div id="pull_request_overview"></div> |
|
156 | <div class="label label-textarea"> | |
|
157 | <label for="pullrequest_submit"></label> | |||
|
158 | </div> | |||
|
159 | <div class="input"> | |||
|
160 | <div class="pr-submit-button"> | |||
|
161 | <input id="pr_submit" class="btn" name="save" type="submit" value="${_('Submit Pull Request')}"> | |||
157 | </div> |
|
162 | </div> | |
158 | </div> |
|
163 | </div> | |
|
164 | </div> | |||
|
165 | </div> | |||
|
166 | </div> | |||
|
167 | </div> | |||
|
168 | ||||
|
169 | </div> | |||
|
170 | ||||
159 | ${h.end_form()} |
|
171 | ${h.end_form()} | |
160 | </div> |
|
172 | </div> | |
161 |
|
173 | |||
@@ -243,8 +255,6 b'' | |||||
243 |
|
255 | |||
244 | var diffDataHandler = function(data) { |
|
256 | var diffDataHandler = function(data) { | |
245 |
|
257 | |||
246 | $('#pull_request_overview').html(data); |
|
|||
247 |
|
||||
248 | var commitElements = data['commits']; |
|
258 | var commitElements = data['commits']; | |
249 | var files = data['files']; |
|
259 | var files = data['files']; | |
250 | var added = data['stats'][0] |
|
260 | var added = data['stats'][0] | |
@@ -303,27 +313,33 b'' | |||||
303 |
|
313 | |||
304 | msg += '<input type="hidden" name="__end__" value="revisions:sequence">' |
|
314 | msg += '<input type="hidden" name="__end__" value="revisions:sequence">' | |
305 | msg += _ngettext( |
|
315 | msg += _ngettext( | |
306 |
' |
|
316 | 'Compare summary: <strong>{0} commit</strong>', | |
307 |
' |
|
317 | 'Compare summary: <strong>{0} commits</strong>', | |
308 | commitElements.length).format(commitElements.length) |
|
318 | commitElements.length).format(commitElements.length) | |
309 |
|
319 | |||
310 |
msg += ' |
|
320 | msg += ''; | |
311 | msg += _ngettext( |
|
321 | msg += _ngettext( | |
312 |
'<strong>{0} file</strong> changed |
|
322 | '<strong>, and {0} file</strong> changed.', | |
313 |
'<strong>{0} files</strong> changed |
|
323 | '<strong>, and {0} files</strong> changed.', | |
314 | files.length).format(files.length) |
|
324 | files.length).format(files.length) | |
315 | msg += '<span class="op-added">{0} lines inserted</span>, <span class="op-deleted">{1} lines deleted</span>.'.format(added, deleted) |
|
|||
316 |
|
325 | |||
317 | msg += '\n\n <a class="" id="pull_request_overview_url" href="{0}" target="_blank">${_('Show detailed compare.')}</a>'.format(url); |
|
326 | msg += '\n Diff: <span class="op-added">{0} lines inserted</span>, <span class="op-deleted">{1} lines deleted </span>.'.format(added, deleted) | |
|
327 | ||||
|
328 | msg += '\n <a class="" id="pull_request_overview_url" href="{0}" target="_blank">${_('Show detailed compare.')}</a>'.format(url); | |||
318 |
|
329 | |||
319 | if (commitElements.length) { |
|
330 | if (commitElements.length) { | |
320 | var commitsLink = '<a href="#pull_request_overview"><strong>{0}</strong></a>'.format(commitElements.length); |
|
331 | var commitsLink = '<a href="#pull_request_overview"><strong>{0}</strong></a>'.format(commitElements.length); | |
321 | prButtonLock(false, msg.replace('__COMMITS__', commitsLink), 'compare'); |
|
332 | prButtonLock(false, msg.replace('__COMMITS__', commitsLink), 'compare'); | |
322 | } |
|
333 | } | |
323 | else { |
|
334 | else { | |
324 | prButtonLock(true, "${_('There are no commits to merge.')}", 'compare'); |
|
335 | var noCommitsMsg = '<span class="alert-text-warning">{0}</span>'.format( | |
|
336 | _gettext('There are no commits to merge.')); | |||
|
337 | prButtonLock(true, noCommitsMsg, 'compare'); | |||
325 | } |
|
338 | } | |
326 |
|
339 | |||
|
340 | //make both panels equal | |||
|
341 | $('.target-panel').height($('.source-panel').height()) | |||
|
342 | ||||
327 | }; |
|
343 | }; | |
328 |
|
344 | |||
329 | reviewersController = new ReviewersController(); |
|
345 | reviewersController = new ReviewersController(); | |
@@ -429,10 +445,12 b'' | |||||
429 |
|
445 | |||
430 | var targetRepoChanged = function(repoData) { |
|
446 | var targetRepoChanged = function(repoData) { | |
431 | // generate new DESC of target repo displayed next to select |
|
447 | // generate new DESC of target repo displayed next to select | |
|
448 | ||||
|
449 | $('#target_repo_desc').html(repoData['description']); | |||
|
450 | ||||
432 | var prLink = pyroutes.url('pullrequest_new', {'repo_name': repoData['name']}); |
|
451 | var prLink = pyroutes.url('pullrequest_new', {'repo_name': repoData['name']}); | |
433 | $('#target_repo_desc').html( |
|
452 | var title = _gettext('Switch target repository with the source.') | |
434 | "<strong>${_('Target repository')}</strong>: {0}. <a href=\"{1}\">Switch base, and use as source.</a>".format(repoData['description'], prLink) |
|
453 | $('#switch_base').html("<a class=\"tooltip\" title=\"{0}\" href=\"{1}\">Switch sides</a>".format(title, prLink)) | |
435 | ); |
|
|||
436 |
|
454 | |||
437 | // generate dynamic select2 for refs. |
|
455 | // generate dynamic select2 for refs. | |
438 | initTargetRefs(repoData['refs']['select2_refs'], |
|
456 | initTargetRefs(repoData['refs']['select2_refs'], |
This diff has been collapsed as it changes many lines, (547 lines changed) Show them Hide them | |||||
@@ -1,6 +1,8 b'' | |||||
1 | <%inherit file="/base/base.mako"/> |
|
1 | <%inherit file="/base/base.mako"/> | |
2 | <%namespace name="base" file="/base/base.mako"/> |
|
2 | <%namespace name="base" file="/base/base.mako"/> | |
3 | <%namespace name="dt" file="/data_table/_dt_elements.mako"/> |
|
3 | <%namespace name="dt" file="/data_table/_dt_elements.mako"/> | |
|
4 | <%namespace name="sidebar" file="/base/sidebar.mako"/> | |||
|
5 | ||||
4 |
|
6 | |||
5 | <%def name="title()"> |
|
7 | <%def name="title()"> | |
6 | ${_('{} Pull Request !{}').format(c.repo_name, c.pull_request.pull_request_id)} |
|
8 | ${_('{} Pull Request !{}').format(c.repo_name, c.pull_request.pull_request_id)} | |
@@ -21,113 +23,6 b'' | |||||
21 | ${self.repo_menu(active='showpullrequest')} |
|
23 | ${self.repo_menu(active='showpullrequest')} | |
22 | </%def> |
|
24 | </%def> | |
23 |
|
25 | |||
24 | <%def name="comments_table(comments, counter_num, todo_comments=False)"> |
|
|||
25 | <% |
|
|||
26 | old_comments = False |
|
|||
27 | if todo_comments: |
|
|||
28 | cls_ = 'todos-content-table' |
|
|||
29 | def sorter(entry): |
|
|||
30 | user_id = entry.author.user_id |
|
|||
31 | resolved = '1' if entry.resolved else '0' |
|
|||
32 | if user_id == c.rhodecode_user.user_id: |
|
|||
33 | # own comments first |
|
|||
34 | user_id = 0 |
|
|||
35 | return '{}'.format(str(entry.comment_id).zfill(10000)) |
|
|||
36 | else: |
|
|||
37 | cls_ = 'comments-content-table' |
|
|||
38 | def sorter(entry): |
|
|||
39 | user_id = entry.author.user_id |
|
|||
40 | return '{}'.format(str(entry.comment_id).zfill(10000)) |
|
|||
41 |
|
||||
42 |
|
||||
43 |
|
||||
44 | %> |
|
|||
45 | <table class="todo-table ${cls_}" data-total-count="${len(comments)}" data-counter="${counter_num}"> |
|
|||
46 |
|
||||
47 | % for loop_obj, comment_obj in h.looper(reversed(sorted(comments, key=sorter))): |
|
|||
48 | <% |
|
|||
49 | display = '' |
|
|||
50 | _cls = '' |
|
|||
51 | %> |
|
|||
52 | <% comment_ver_index = comment_obj.get_index_version(getattr(c, 'versions', [])) %> |
|
|||
53 | <% |
|
|||
54 | prev_comment_ver_index = 0 |
|
|||
55 | if loop_obj.previous: |
|
|||
56 | prev_comment_ver_index = loop_obj.previous.get_index_version(getattr(c, 'versions', [])) |
|
|||
57 | %> |
|
|||
58 | <% hidden_at_ver = comment_obj.outdated_at_version_js(c.at_version_num) %> |
|
|||
59 | <% is_from_old_ver = comment_obj.older_than_version_js(c.at_version_num) %> |
|
|||
60 | <% |
|
|||
61 | if (prev_comment_ver_index > comment_ver_index) and old_comments is False: |
|
|||
62 | old_comments = True |
|
|||
63 | %> |
|
|||
64 | % if todo_comments: |
|
|||
65 | % if comment_obj.resolved: |
|
|||
66 | <% _cls = 'resolved-todo' %> |
|
|||
67 | <% display = 'none' %> |
|
|||
68 | % endif |
|
|||
69 | % else: |
|
|||
70 | ## SKIP TODOs we display them in other area |
|
|||
71 | % if comment_obj.is_todo: |
|
|||
72 | <% display = 'none' %> |
|
|||
73 | % endif |
|
|||
74 | ## Skip outdated comments |
|
|||
75 | % if comment_obj.outdated: |
|
|||
76 | <% display = 'none' %> |
|
|||
77 | <% _cls = 'hidden-comment' %> |
|
|||
78 | % endif |
|
|||
79 | % endif |
|
|||
80 |
|
||||
81 | % if not todo_comments and old_comments: |
|
|||
82 | <tr class="old-comments-marker"> |
|
|||
83 | <td colspan="3"> <code>comments from older versions</code> </td> |
|
|||
84 | </tr> |
|
|||
85 | ## reset markers so we only show this marker once |
|
|||
86 | <% old_comments = None %> |
|
|||
87 | % endif |
|
|||
88 |
|
||||
89 | <tr class="${_cls}" style="display: ${display};"> |
|
|||
90 | <td class="td-todo-number"> |
|
|||
91 |
|
||||
92 | <a class="${('todo-resolved' if comment_obj.resolved else '')} permalink" |
|
|||
93 | href="#comment-${comment_obj.comment_id}" |
|
|||
94 | onclick="return Rhodecode.comments.scrollToComment($('#comment-${comment_obj.comment_id}'), 0, ${hidden_at_ver})"> |
|
|||
95 |
|
||||
96 | % if todo_comments: |
|
|||
97 | % if comment_obj.is_inline: |
|
|||
98 | <i class="tooltip icon-code" title="Inline TODO comment ${('made in older version (v{})'.format(comment_ver_index) if is_from_old_ver == 'true' else 'made in this version')}."></i> |
|
|||
99 | % else: |
|
|||
100 | <i class="tooltip icon-comment" title="General TODO comment ${('made in older version (v{})'.format(comment_ver_index) if is_from_old_ver == 'true' else 'made in this version')}."></i> |
|
|||
101 | % endif |
|
|||
102 | % else: |
|
|||
103 | % if comment_obj.outdated: |
|
|||
104 | <i class="tooltip icon-comment-toggle" title="Inline Outdated made in v${comment_ver_index}."></i> |
|
|||
105 | % elif comment_obj.is_inline: |
|
|||
106 | <i class="tooltip icon-code" title="Inline comment ${('made in older version (v{})'.format(comment_ver_index) if is_from_old_ver == 'true' else 'made in this version')}."></i> |
|
|||
107 | % else: |
|
|||
108 | <i class="tooltip icon-comment" title="General comment ${('made in older version (v{})'.format(comment_ver_index) if is_from_old_ver == 'true' else 'made in this version')}."></i> |
|
|||
109 | % endif |
|
|||
110 | % endif |
|
|||
111 |
|
||||
112 | #${comment_obj.comment_id} |
|
|||
113 | </a> |
|
|||
114 | </td> |
|
|||
115 |
|
||||
116 | <td class="td-todo-gravatar"> |
|
|||
117 | ${base.gravatar(comment_obj.author.email, 16, user=comment_obj.author, tooltip=True, extra_class=['no-margin'])} |
|
|||
118 | </td> |
|
|||
119 | <td class="todo-comment-text-wrapper"> |
|
|||
120 | <div class="tooltip todo-comment-text timeago" title="${h.format_date(comment_obj.created_on)}" datetime="${comment_obj.created_on}${h.get_timezone(comment_obj.created_on, time_is_local=True)}"> |
|
|||
121 | <code>${h.chop_at_smart(comment_obj.text, '\n', suffix_if_chopped='...')}</code> |
|
|||
122 | </div> |
|
|||
123 | </td> |
|
|||
124 | </tr> |
|
|||
125 | % endfor |
|
|||
126 |
|
||||
127 | </table> |
|
|||
128 |
|
||||
129 | </%def> |
|
|||
130 |
|
||||
131 |
|
26 | |||
132 | <%def name="main()"> |
|
27 | <%def name="main()"> | |
133 | ## Container to gather extracted Tickets |
|
28 | ## Container to gather extracted Tickets | |
@@ -140,6 +35,7 b'' | |||||
140 | // TODO: marcink switch this to pyroutes |
|
35 | // TODO: marcink switch this to pyroutes | |
141 | AJAX_COMMENT_DELETE_URL = "${h.route_path('pullrequest_comment_delete',repo_name=c.repo_name,pull_request_id=c.pull_request.pull_request_id,comment_id='__COMMENT_ID__')}"; |
|
36 | AJAX_COMMENT_DELETE_URL = "${h.route_path('pullrequest_comment_delete',repo_name=c.repo_name,pull_request_id=c.pull_request.pull_request_id,comment_id='__COMMENT_ID__')}"; | |
142 | templateContext.pull_request_data.pull_request_id = ${c.pull_request.pull_request_id}; |
|
37 | templateContext.pull_request_data.pull_request_id = ${c.pull_request.pull_request_id}; | |
|
38 | templateContext.pull_request_data.pull_request_version = '${request.GET.get('version', '')}'; | |||
143 | </script> |
|
39 | </script> | |
144 |
|
40 | |||
145 | <div class="box"> |
|
41 | <div class="box"> | |
@@ -226,7 +122,7 b'' | |||||
226 |
|
122 | |||
227 | ${_('of')} <a href="${h.route_path('repo_summary', repo_name=c.pull_request.target_repo.repo_name)}">${c.pull_request.target_repo.repo_name}</a> |
|
123 | ${_('of')} <a href="${h.route_path('repo_summary', repo_name=c.pull_request.target_repo.repo_name)}">${c.pull_request.target_repo.repo_name}</a> | |
228 |
|
124 | |||
229 |
<a class="source-details-action" href="#expand-source-details" onclick="return |
|
125 | <a class="source-details-action" href="#expand-source-details" onclick="return toggleElement(this, '.source-details')" data-toggle-on='<i class="icon-angle-down">more details</i>' data-toggle-off='<i class="icon-angle-up">less details</i>'> | |
230 | <i class="icon-angle-down">more details</i> |
|
126 | <i class="icon-angle-down">more details</i> | |
231 | </a> |
|
127 | </a> | |
232 |
|
128 | |||
@@ -643,101 +539,12 b'' | |||||
643 | </div> |
|
539 | </div> | |
644 |
|
540 | |||
645 |
|
541 | |||
646 | ### NAVBOG RIGHT |
|
542 | ### NAV SIDEBAR | |
647 | <style> |
|
|||
648 |
|
||||
649 | .right-sidebar { |
|
|||
650 | position: fixed; |
|
|||
651 | top: 0px; |
|
|||
652 | bottom: 0; |
|
|||
653 | right: 0; |
|
|||
654 |
|
||||
655 | background: #fafafa; |
|
|||
656 | z-index: 50; |
|
|||
657 | } |
|
|||
658 |
|
||||
659 | .right-sidebar { |
|
|||
660 | border-left: 1px solid #dbdbdb; |
|
|||
661 | } |
|
|||
662 |
|
||||
663 | .right-sidebar.right-sidebar-expanded { |
|
|||
664 | width: 320px; |
|
|||
665 | overflow: scroll; |
|
|||
666 | } |
|
|||
667 |
|
||||
668 | .right-sidebar.right-sidebar-collapsed { |
|
|||
669 | width: 50px; |
|
|||
670 | padding: 0; |
|
|||
671 | display: block; |
|
|||
672 | overflow: hidden; |
|
|||
673 | } |
|
|||
674 |
|
||||
675 | .sidenav { |
|
|||
676 | float: right; |
|
|||
677 | will-change: min-height; |
|
|||
678 | background: #fafafa; |
|
|||
679 | width: 100%; |
|
|||
680 | padding-top: 50px; |
|
|||
681 | } |
|
|||
682 |
|
||||
683 | .sidebar-toggle { |
|
|||
684 | height: 30px; |
|
|||
685 | text-align: center; |
|
|||
686 | margin: 15px 0px 0 0; |
|
|||
687 | } |
|
|||
688 | .sidebar-toggle a { |
|
|||
689 |
|
||||
690 | } |
|
|||
691 |
|
||||
692 | .sidebar-content { |
|
|||
693 | margin-left: 15px; |
|
|||
694 | margin-right: 15px; |
|
|||
695 | } |
|
|||
696 |
|
||||
697 | .sidebar-heading { |
|
|||
698 | font-size: 1.2em; |
|
|||
699 | font-weight: 700; |
|
|||
700 | margin-top: 10px; |
|
|||
701 | } |
|
|||
702 |
|
||||
703 | .sidebar-element { |
|
|||
704 | margin-top: 20px; |
|
|||
705 | } |
|
|||
706 | .right-sidebar-collapsed-state { |
|
|||
707 | display: flex; |
|
|||
708 | flex-direction: column; |
|
|||
709 | justify-content: center; |
|
|||
710 | align-items: center; |
|
|||
711 | padding: 0 10px; |
|
|||
712 | cursor: pointer; |
|
|||
713 | font-size: 1.3em; |
|
|||
714 | margin: 0 -15px; |
|
|||
715 | } |
|
|||
716 |
|
||||
717 | .right-sidebar-collapsed-state:hover { |
|
|||
718 | background-color: #dbd9da; |
|
|||
719 | } |
|
|||
720 |
|
||||
721 | .old-comments-marker { |
|
|||
722 | text-align: center; |
|
|||
723 | } |
|
|||
724 |
|
||||
725 | .old-comments-marker td { |
|
|||
726 | padding-top: 15px; |
|
|||
727 | border-bottom: 1px solid #dbd9da; |
|
|||
728 | } |
|
|||
729 |
|
||||
730 | #add_reviewer { |
|
|||
731 | padding-top: 10px; |
|
|||
732 | } |
|
|||
733 |
|
||||
734 | </style> |
|
|||
735 |
|
||||
736 | <aside class="right-sidebar right-sidebar-expanded" id="pr-nav-sticky" style="display: none"> |
|
543 | <aside class="right-sidebar right-sidebar-expanded" id="pr-nav-sticky" style="display: none"> | |
737 | <div class="sidenav navbar__inner" > |
|
544 | <div class="sidenav navbar__inner" > | |
738 | ## TOGGLE |
|
545 | ## TOGGLE | |
739 | <div class="sidebar-toggle" onclick="toggleSidebar(); return false"> |
|
546 | <div class="sidebar-toggle" onclick="toggleSidebar(); return false"> | |
740 | <a href="#toggleSidebar"> |
|
547 | <a href="#toggleSidebar" class="grey-link-action"> | |
741 |
|
548 | |||
742 | </a> |
|
549 | </a> | |
743 | </div> |
|
550 | </div> | |
@@ -747,8 +554,12 b'' | |||||
747 |
|
554 | |||
748 | ## RULES SUMMARY/RULES |
|
555 | ## RULES SUMMARY/RULES | |
749 | <div class="sidebar-element clear-both"> |
|
556 | <div class="sidebar-element clear-both"> | |
|
557 | <% vote_title = _ungettext( | |||
|
558 | 'Status calculated based on votes from {} reviewer', | |||
|
559 | 'Status calculated based on votes from {} reviewers', len(c.allowed_reviewers)).format(len(c.allowed_reviewers)) | |||
|
560 | %> | |||
750 |
|
561 | |||
751 |
<div class="tooltip right-sidebar-collapsed-state" style="display: none" onclick="toggleSidebar(); return false" title="${ |
|
562 | <div class="tooltip right-sidebar-collapsed-state" style="display: none" onclick="toggleSidebar(); return false" title="${vote_title}"> | |
752 | <i class="icon-circle review-status-${c.pull_request_review_status}"></i> |
|
563 | <i class="icon-circle review-status-${c.pull_request_review_status}"></i> | |
753 | ${len(c.allowed_reviewers)} |
|
564 | ${len(c.allowed_reviewers)} | |
754 | </div> |
|
565 | </div> | |
@@ -769,7 +580,7 b'' | |||||
769 |
|
580 | |||
770 | ## REVIEWERS |
|
581 | ## REVIEWERS | |
771 | <div class="right-sidebar-expanded-state pr-details-title"> |
|
582 | <div class="right-sidebar-expanded-state pr-details-title"> | |
772 | <span class="tooltip sidebar-heading" title="${_ungettext('Review status calculated based on {} reviewer vote', 'Review status calculated based on {} reviewers votes', len(c.allowed_reviewers)).format(len(c.allowed_reviewers))}"> |
|
583 | <span class="tooltip sidebar-heading" title="${vote_title}"> | |
773 | <i class="icon-circle review-status-${c.pull_request_review_status}"></i> |
|
584 | <i class="icon-circle review-status-${c.pull_request_review_status}"></i> | |
774 | ${_('Reviewers')} |
|
585 | ${_('Reviewers')} | |
775 | </span> |
|
586 | </span> | |
@@ -846,7 +657,7 b'' | |||||
846 |
|
657 | |||
847 | % if not c.at_version: |
|
658 | % if not c.at_version: | |
848 | % if c.resolved_comments: |
|
659 | % if c.resolved_comments: | |
849 |
<span class="block-right action_button last-item noselect" onclick="$('.unresolved-todo-text').toggle(); return |
|
660 | <span class="block-right action_button last-item noselect" onclick="$('.unresolved-todo-text').toggle(); return toggleElement(this, '.resolved-todo');" data-toggle-on="Show resolved" data-toggle-off="Hide resolved">Show resolved</span> | |
850 | % else: |
|
661 | % else: | |
851 | <span class="block-right last-item noselect">Show resolved</span> |
|
662 | <span class="block-right last-item noselect">Show resolved</span> | |
852 | % endif |
|
663 | % endif | |
@@ -863,7 +674,7 b'' | |||||
863 | </table> |
|
674 | </table> | |
864 | % else: |
|
675 | % else: | |
865 | % if c.unresolved_comments + c.resolved_comments: |
|
676 | % if c.unresolved_comments + c.resolved_comments: | |
866 | ${comments_table(c.unresolved_comments + c.resolved_comments, len(c.unresolved_comments), todo_comments=True)} |
|
677 | ${sidebar.comments_table(c.unresolved_comments + c.resolved_comments, len(c.unresolved_comments), todo_comments=True)} | |
867 | % else: |
|
678 | % else: | |
868 | <table> |
|
679 | <table> | |
869 | <tr> |
|
680 | <tr> | |
@@ -882,6 +693,8 b'' | |||||
882 | <div class="tooltip right-sidebar-collapsed-state" style="display: none" onclick="toggleSidebar(); return false" title="${_('Comments')}"> |
|
693 | <div class="tooltip right-sidebar-collapsed-state" style="display: none" onclick="toggleSidebar(); return false" title="${_('Comments')}"> | |
883 | <i class="icon-comment" style="color: #949494"></i> |
|
694 | <i class="icon-comment" style="color: #949494"></i> | |
884 | <span id="comments-count">${len(c.inline_comments_flat+c.comments)}</span> |
|
695 | <span id="comments-count">${len(c.inline_comments_flat+c.comments)}</span> | |
|
696 | <span class="display-none" id="general-comments-count">${len(c.comments)}</span> | |||
|
697 | <span class="display-none" id="inline-comments-count">${len(c.inline_comments_flat)}</span> | |||
885 | </div> |
|
698 | </div> | |
886 |
|
699 | |||
887 | <div class="right-sidebar-expanded-state pr-details-title"> |
|
700 | <div class="right-sidebar-expanded-state pr-details-title"> | |
@@ -903,7 +716,7 b'' | |||||
903 | </span> |
|
716 | </span> | |
904 |
|
717 | |||
905 | % if outdated_comm_count_ver: |
|
718 | % if outdated_comm_count_ver: | |
906 |
<span class="block-right action_button last-item noselect" onclick="return |
|
719 | <span class="block-right action_button last-item noselect" onclick="return toggleElement(this, '.hidden-comment');" data-toggle-on="Show outdated" data-toggle-off="Hide outdated">Show outdated</span> | |
907 | % else: |
|
720 | % else: | |
908 | <span class="block-right last-item noselect">Show hidden</span> |
|
721 | <span class="block-right last-item noselect">Show hidden</span> | |
909 | % endif |
|
722 | % endif | |
@@ -912,7 +725,7 b'' | |||||
912 |
|
725 | |||
913 | <div class="right-sidebar-expanded-state pr-details-content"> |
|
726 | <div class="right-sidebar-expanded-state pr-details-content"> | |
914 | % if c.inline_comments_flat + c.comments: |
|
727 | % if c.inline_comments_flat + c.comments: | |
915 | ${comments_table(c.inline_comments_flat + c.comments, len(c.inline_comments_flat+c.comments))} |
|
728 | ${sidebar.comments_table(c.inline_comments_flat + c.comments, len(c.inline_comments_flat+c.comments))} | |
916 | % else: |
|
729 | % else: | |
917 | <table> |
|
730 | <table> | |
918 | <tr> |
|
731 | <tr> | |
@@ -942,7 +755,7 b'' | |||||
942 | <div class="right-sidebar-expanded-state pr-details-content"> |
|
755 | <div class="right-sidebar-expanded-state pr-details-content"> | |
943 | <table> |
|
756 | <table> | |
944 |
|
757 | |||
945 |
<tr><td><code>${_(' |
|
758 | <tr><td><code>${_('In pull request description')}:</code></td></tr> | |
946 | % if c.referenced_desc_issues: |
|
759 | % if c.referenced_desc_issues: | |
947 | % for ticket_dict in c.referenced_desc_issues: |
|
760 | % for ticket_dict in c.referenced_desc_issues: | |
948 | <tr> |
|
761 | <tr> | |
@@ -961,7 +774,7 b'' | |||||
961 | </tr> |
|
774 | </tr> | |
962 | % endif |
|
775 | % endif | |
963 |
|
776 | |||
964 |
<tr><td style="padding-top: 10px"><code>${_(' |
|
777 | <tr><td style="padding-top: 10px"><code>${_('In commit messages')}:</code></td></tr> | |
965 | % if c.referenced_commit_issues: |
|
778 | % if c.referenced_commit_issues: | |
966 | % for ticket_dict in c.referenced_commit_issues: |
|
779 | % for ticket_dict in c.referenced_commit_issues: | |
967 | <tr> |
|
780 | <tr> | |
@@ -1000,63 +813,12 b'' | |||||
1000 |
|
813 | |||
1001 |
|
|
814 | updateController = new UpdatePrController(); | |
1002 |
|
815 | |||
1003 | /** leak object to top level scope **/ |
|
816 | window.reviewerRulesData = ${c.pull_request_default_reviewers_data_json | n}; | |
1004 | window.PullRequestPresenceController; |
|
817 | window.setReviewersData = ${c.pull_request_set_reviewers_data_json | n}; | |
1005 |
|
818 | |||
1006 | (function () { |
|
819 | (function () { | |
1007 | "use strict"; |
|
820 | "use strict"; | |
1008 |
|
821 | |||
1009 | window.PullRequestPresenceController = function (channel) { |
|
|||
1010 | var self = this; |
|
|||
1011 | this.channel = channel; |
|
|||
1012 | this.users = {}; |
|
|||
1013 |
|
||||
1014 | this.storeUsers = function (users) { |
|
|||
1015 | self.users = {} |
|
|||
1016 | $.each(users, function(index, value) { |
|
|||
1017 | var userId = value.state.id; |
|
|||
1018 | self.users[userId] = value.state; |
|
|||
1019 | }) |
|
|||
1020 | } |
|
|||
1021 |
|
||||
1022 | this.render = function () { |
|
|||
1023 | $.each($('.reviewer_entry'), function(index, value) { |
|
|||
1024 | var userData = $(value).data(); |
|
|||
1025 | if(self.users[userData.reviewerUserId] !== undefined){ |
|
|||
1026 | $(value).find('.presence-state').show(); |
|
|||
1027 | } else { |
|
|||
1028 | $(value).find('.presence-state').hide(); |
|
|||
1029 | } |
|
|||
1030 | }) |
|
|||
1031 | }; |
|
|||
1032 |
|
||||
1033 | this.handlePresence = function (data) { |
|
|||
1034 |
|
||||
1035 | if (data.type == 'presence' && data.channel === self.channel) { |
|
|||
1036 | this.storeUsers(data.users); |
|
|||
1037 | this.render() |
|
|||
1038 | } |
|
|||
1039 | }; |
|
|||
1040 |
|
||||
1041 | this.handleChannelUpdate = function (data) { |
|
|||
1042 |
|
||||
1043 | if (data.channel === this.channel) { |
|
|||
1044 | this.storeUsers(data.state.users); |
|
|||
1045 | this.render() |
|
|||
1046 | } |
|
|||
1047 |
|
||||
1048 | }; |
|
|||
1049 |
|
||||
1050 | /* subscribe our chat to topics that are interesting to it */ |
|
|||
1051 | $.Topic('/connection_controller/channel_update').subscribe(this.handleChannelUpdate.bind(this)); |
|
|||
1052 | $.Topic('/connection_controller/presence').subscribe(this.handlePresence.bind(this)); |
|
|||
1053 | }; |
|
|||
1054 |
|
||||
1055 | })(); |
|
|||
1056 |
|
||||
1057 |
|
||||
1058 | $(function () { |
|
|||
1059 |
|
||||
1060 |
|
|
822 | // custom code mirror | |
1061 |
|
|
823 | var codeMirrorInstance = $('#pr-description-input').get(0).MarkupForm.cm; | |
1062 |
|
824 | |||
@@ -1078,12 +840,13 b' window.PullRequestPresenceController;' | |||||
1078 |
|
|
840 | }, | |
1079 |
|
841 | |||
1080 |
|
|
842 | edit: function (event) { | |
|
843 | var cmInstance = $('#pr-description-input').get(0).MarkupForm.cm; | |||
1081 |
|
|
844 | this.viewFields.hide(); | |
1082 |
|
|
845 | this.editButton.hide(); | |
1083 |
|
|
846 | this.deleteButton.hide(); | |
1084 |
|
|
847 | this.closeButton.show(); | |
1085 |
|
|
848 | this.editFields.show(); | |
1086 |
|
|
849 | cmInstance.refresh(); | |
1087 |
|
|
850 | }, | |
1088 |
|
851 | |||
1089 |
|
|
852 | view: function (event) { | |
@@ -1095,88 +858,24 b' window.PullRequestPresenceController;' | |||||
1095 |
|
|
858 | } | |
1096 |
|
|
859 | }; | |
1097 |
|
860 | |||
1098 | var ReviewersPanel = { |
|
861 | PRDetails.init(); | |
1099 | editButton: $('#open_edit_reviewers'), |
|
862 | ReviewersPanel.init(reviewerRulesData, setReviewersData); | |
1100 | closeButton: $('#close_edit_reviewers'), |
|
|||
1101 | addButton: $('#add_reviewer'), |
|
|||
1102 | removeButtons: $('.reviewer_member_remove,.reviewer_member_mandatory_remove'), |
|
|||
1103 | reviewRules: ${c.pull_request_default_reviewers_data_json | n}, |
|
|||
1104 | setReviewers: ${c.pull_request_set_reviewers_data_json | n}, |
|
|||
1105 |
|
||||
1106 | init: function () { |
|
|||
1107 | var self = this; |
|
|||
1108 | this.editButton.on('click', function (e) { |
|
|||
1109 | self.edit(); |
|
|||
1110 | }); |
|
|||
1111 | this.closeButton.on('click', function (e) { |
|
|||
1112 | self.close(); |
|
|||
1113 | self.renderReviewers(); |
|
|||
1114 | }); |
|
|||
1115 |
|
||||
1116 | self.renderReviewers(); |
|
|||
1117 |
|
||||
1118 | }, |
|
|||
1119 |
|
||||
1120 | renderReviewers: function () { |
|
|||
1121 |
|
||||
1122 | $('#review_members').html('') |
|
|||
1123 | $.each(this.setReviewers.reviewers, function (key, val) { |
|
|||
1124 | var member = val; |
|
|||
1125 |
|
863 | |||
1126 | var entry = renderTemplate('reviewMemberEntry', { |
|
864 | window.showOutdated = function (self) { | |
1127 | 'member': member, |
|
|||
1128 | 'mandatory': member.mandatory, |
|
|||
1129 | 'reasons': member.reasons, |
|
|||
1130 | 'allowed_to_update': member.allowed_to_update, |
|
|||
1131 | 'review_status': member.review_status, |
|
|||
1132 | 'review_status_label': member.review_status_label, |
|
|||
1133 | 'user_group': member.user_group, |
|
|||
1134 | 'create': false |
|
|||
1135 | }); |
|
|||
1136 |
|
||||
1137 | $('#review_members').append(entry) |
|
|||
1138 | }); |
|
|||
1139 | tooltipActivate(); |
|
|||
1140 |
|
||||
1141 | }, |
|
|||
1142 |
|
||||
1143 | edit: function (event) { |
|
|||
1144 | this.editButton.hide(); |
|
|||
1145 | this.closeButton.show(); |
|
|||
1146 | this.addButton.show(); |
|
|||
1147 | $(this.removeButtons.selector).css('visibility', 'visible'); |
|
|||
1148 | // review rules |
|
|||
1149 | reviewersController.loadReviewRules(this.reviewRules); |
|
|||
1150 | }, |
|
|||
1151 |
|
||||
1152 | close: function (event) { |
|
|||
1153 | this.editButton.show(); |
|
|||
1154 | this.closeButton.hide(); |
|
|||
1155 | this.addButton.hide(); |
|
|||
1156 | $(this.removeButtons.selector).css('visibility', 'hidden'); |
|
|||
1157 | // hide review rules |
|
|||
1158 | reviewersController.hideReviewRules() |
|
|||
1159 | } |
|
|||
1160 | }; |
|
|||
1161 |
|
||||
1162 | PRDetails.init(); |
|
|||
1163 | ReviewersPanel.init(); |
|
|||
1164 |
|
||||
1165 | showOutdated = function (self) { |
|
|||
1166 |
|
|
865 | $('.comment-inline.comment-outdated').show(); | |
1167 |
|
|
866 | $('.filediff-outdated').show(); | |
1168 |
|
|
867 | $('.showOutdatedComments').hide(); | |
1169 |
|
|
868 | $('.hideOutdatedComments').show(); | |
1170 |
|
|
869 | }; | |
1171 |
|
870 | |||
1172 |
|
|
871 | window.hideOutdated = function (self) { | |
1173 |
|
|
872 | $('.comment-inline.comment-outdated').hide(); | |
1174 |
|
|
873 | $('.filediff-outdated').hide(); | |
1175 |
|
|
874 | $('.hideOutdatedComments').hide(); | |
1176 |
|
|
875 | $('.showOutdatedComments').show(); | |
1177 |
|
|
876 | }; | |
1178 |
|
877 | |||
1179 |
|
|
878 | window.refreshMergeChecks = function () { | |
1180 |
|
|
879 | var loadUrl = "${request.current_route_path(_query=dict(merge_checks=1))}"; | |
1181 |
|
|
880 | $('.pull-request-merge').css('opacity', 0.3); | |
1182 |
|
|
881 | $('.action-buttons-extra').css('opacity', 0.3); | |
@@ -1190,76 +889,7 b' window.PullRequestPresenceController;' | |||||
1190 |
|
|
889 | ); | |
1191 |
|
|
890 | }; | |
1192 |
|
891 | |||
1193 | refreshComments = function () { |
|
892 | window.closePullRequest = function (status) { | |
1194 | var params = { |
|
|||
1195 | 'pull_request_id': templateContext.pull_request_data.pull_request_id, |
|
|||
1196 | 'repo_name': templateContext.repo_name, |
|
|||
1197 | 'version': '${request.GET.get('version', '')}', |
|
|||
1198 | }; |
|
|||
1199 | var data = {"comments[]": ["1"]}; |
|
|||
1200 | var loadUrl = pyroutes.url('pullrequest_comments', params); |
|
|||
1201 | var $targetElem = $('.comments-content-table'); |
|
|||
1202 | $targetElem.css('opacity', 0.3); |
|
|||
1203 | $targetElem.load( |
|
|||
1204 | loadUrl, data, function (responseText, textStatus, jqXHR) { |
|
|||
1205 | if (jqXHR.status !== 200) { |
|
|||
1206 | return false; |
|
|||
1207 | } |
|
|||
1208 | var $counterElem = $('#comments-count'); |
|
|||
1209 | var newCount = $(responseText).data('counter'); |
|
|||
1210 | if (newCount !== undefined) { |
|
|||
1211 | var callback = function () { |
|
|||
1212 | $counterElem.animate({'opacity': 1.00}, 200) |
|
|||
1213 | $counterElem.html(newCount); |
|
|||
1214 | }; |
|
|||
1215 | $counterElem.animate({'opacity': 0.15}, 200, callback); |
|
|||
1216 | } |
|
|||
1217 |
|
||||
1218 |
|
||||
1219 | $targetElem.css('opacity', 1); |
|
|||
1220 | tooltipActivate(); |
|
|||
1221 | } |
|
|||
1222 | ); |
|
|||
1223 | } |
|
|||
1224 |
|
||||
1225 | refreshTODOs = function () { |
|
|||
1226 | var params = { |
|
|||
1227 | 'pull_request_id': templateContext.pull_request_data.pull_request_id, |
|
|||
1228 | 'repo_name': templateContext.repo_name, |
|
|||
1229 | 'version': '${request.GET.get('version', '')}', |
|
|||
1230 | }; |
|
|||
1231 | var data = {"comments[]": ["1"]}; |
|
|||
1232 | var loadUrl = pyroutes.url('pullrequest_todos', params); |
|
|||
1233 | var $targetElem = $('.todos-content-table'); |
|
|||
1234 | $targetElem.css('opacity', 0.3); |
|
|||
1235 | $targetElem.load( |
|
|||
1236 | loadUrl, data, function (responseText, textStatus, jqXHR) { |
|
|||
1237 | if (jqXHR.status !== 200) { |
|
|||
1238 | return false; |
|
|||
1239 | } |
|
|||
1240 | var $counterElem = $('#todos-count') |
|
|||
1241 | var newCount = $(responseText).data('counter'); |
|
|||
1242 | if (newCount !== undefined) { |
|
|||
1243 | var callback = function () { |
|
|||
1244 | $counterElem.animate({'opacity': 1.00}, 200) |
|
|||
1245 | $counterElem.html(newCount); |
|
|||
1246 | }; |
|
|||
1247 | $counterElem.animate({'opacity': 0.15}, 200, callback); |
|
|||
1248 | } |
|
|||
1249 |
|
||||
1250 | $targetElem.css('opacity', 1); |
|
|||
1251 | tooltipActivate(); |
|
|||
1252 | } |
|
|||
1253 | ); |
|
|||
1254 |
|
||||
1255 | } |
|
|||
1256 |
|
||||
1257 | refreshAllComments = function() { |
|
|||
1258 | refreshComments(); |
|
|||
1259 | refreshTODOs(); |
|
|||
1260 | } |
|
|||
1261 |
|
||||
1262 | closePullRequest = function (status) { |
|
|||
1263 |
|
|
893 | if (!confirm(_gettext('Are you sure to close this pull request without merging?'))) { | |
1264 |
|
|
894 | return false; | |
1265 |
|
|
895 | } | |
@@ -1269,6 +899,7 b' window.PullRequestPresenceController;' | |||||
1269 |
|
|
899 | $(generalCommentForm.submitForm).submit(); | |
1270 |
|
|
900 | }; | |
1271 |
|
901 | |||
|
902 | //TODO this functionality is now missing | |||
1272 |
|
|
903 | $('#show-outdated-comments').on('click', function (e) { | |
1273 |
|
|
904 | var button = $(this); | |
1274 |
|
|
905 | var outdated = $('.comment-outdated'); | |
@@ -1282,22 +913,6 b' window.PullRequestPresenceController;' | |||||
1282 |
|
|
913 | } | |
1283 |
|
|
914 | }); | |
1284 |
|
915 | |||
1285 | $('.show-inline-comments').on('change', function (e) { |
|
|||
1286 | var show = 'none'; |
|
|||
1287 | var target = e.currentTarget; |
|
|||
1288 | if (target.checked) { |
|
|||
1289 | show = '' |
|
|||
1290 | } |
|
|||
1291 | var boxid = $(target).attr('id_for'); |
|
|||
1292 | var comments = $('#{0} .inline-comments'.format(boxid)); |
|
|||
1293 | var fn_display = function (idx) { |
|
|||
1294 | $(this).css('display', show); |
|
|||
1295 | }; |
|
|||
1296 | $(comments).each(fn_display); |
|
|||
1297 | var btns = $('#{0} .inline-comments-button'.format(boxid)); |
|
|||
1298 | $(btns).each(fn_display); |
|
|||
1299 | }); |
|
|||
1300 |
|
||||
1301 |
|
|
916 | $('#merge_pull_request_form').submit(function () { | |
1302 |
|
|
917 | if (!$('#merge_pull_request').attr('disabled')) { | |
1303 |
|
|
918 | $('#merge_pull_request').attr('disabled', 'disabled'); | |
@@ -1322,7 +937,6 b' window.PullRequestPresenceController;' | |||||
1322 |
|
|
937 | "${c.repo_name}", "${c.pull_request.pull_request_id}"); | |
1323 |
|
|
938 | }); | |
1324 |
|
939 | |||
1325 |
|
||||
1326 |
|
|
940 | // fixing issue with caches on firefox | |
1327 |
|
|
941 | $('#update_commits').removeAttr("disabled"); | |
1328 |
|
942 | |||
@@ -1343,6 +957,22 b' window.PullRequestPresenceController;' | |||||
1343 |
|
|
957 | } | |
1344 |
|
|
958 | }); | |
1345 |
|
959 | |||
|
960 | $('.show-inline-comments').on('change', function (e) { | |||
|
961 | var show = 'none'; | |||
|
962 | var target = e.currentTarget; | |||
|
963 | if (target.checked) { | |||
|
964 | show = '' | |||
|
965 | } | |||
|
966 | var boxid = $(target).attr('id_for'); | |||
|
967 | var comments = $('#{0} .inline-comments'.format(boxid)); | |||
|
968 | var fn_display = function (idx) { | |||
|
969 | $(this).css('display', show); | |||
|
970 | }; | |||
|
971 | $(comments).each(fn_display); | |||
|
972 | var btns = $('#{0} .inline-comments-button'.format(boxid)); | |||
|
973 | $(btns).each(fn_display); | |||
|
974 | }); | |||
|
975 | ||||
1346 |
|
|
976 | // register submit callback on commentForm form to track TODOs | |
1347 |
|
|
977 | window.commentFormGlobalSubmitSuccessCallback = function () { | |
1348 |
|
|
978 | refreshMergeChecks(); | |
@@ -1350,91 +980,12 b' window.PullRequestPresenceController;' | |||||
1350 |
|
980 | |||
1351 |
|
|
981 | ReviewerAutoComplete('#user'); | |
1352 |
|
982 | |||
1353 | }) |
|
983 | })(); | |
1354 |
|
984 | |||
1355 |
|
|
985 | $(document).ready(function () { | |
1356 |
|
986 | |||
1357 | var $sideBar = $('.right-sidebar'); |
|
|||
1358 | var marginExpVal = '320' |
|
|||
1359 | var marginColVal = '50' |
|
|||
1360 | var marginExpanded = {'margin': '0 {0}px 0 0'.format(marginExpVal)}; |
|
|||
1361 | var marginCollapsed = {'margin': '0 {0}px 0 0'.format(marginColVal)}; |
|
|||
1362 | var marginExpandedHeader = {'margin': '0 -{0}px 0 0'.format(marginExpVal), 'z-index': 10000}; |
|
|||
1363 | var marginCollapsedHeader = {'margin': '0 -{0}px 0 0'.format(marginColVal), 'z-index': 10000}; |
|
|||
1364 |
|
||||
1365 | var updateStickyHeader = function() { |
|
|||
1366 | if (window.updateSticky !== undefined) { |
|
|||
1367 | // potentially our comments change the active window size, so we |
|
|||
1368 | // notify sticky elements |
|
|||
1369 | updateSticky() |
|
|||
1370 | } |
|
|||
1371 | } |
|
|||
1372 |
|
||||
1373 | var expandSidebar = function() { |
|
|||
1374 | var $sideBar = $('.right-sidebar'); |
|
|||
1375 | $('.outerwrapper').css(marginExpanded); |
|
|||
1376 | $('.header').css(marginExpandedHeader); |
|
|||
1377 | $('.sidebar-toggle a').html('<i class="icon-right" style="margin-right: -10px"></i><i class="icon-right"></i>'); |
|
|||
1378 | $('.right-sidebar-collapsed-state').hide(); |
|
|||
1379 | $('.right-sidebar-expanded-state').show(); |
|
|||
1380 |
|
||||
1381 | $sideBar.addClass('right-sidebar-expanded') |
|
|||
1382 | $sideBar.removeClass('right-sidebar-collapsed') |
|
|||
1383 | } |
|
|||
1384 |
|
||||
1385 | var collapseSidebar = function() { |
|
|||
1386 | var $sideBar = $('.right-sidebar'); |
|
|||
1387 | $('.outerwrapper').css(marginCollapsed); |
|
|||
1388 | $('.header').css(marginCollapsedHeader); |
|
|||
1389 | $('.sidebar-toggle a').html('<i class="icon-left" style="margin-right: -10px"></i><i class="icon-left"></i>'); |
|
|||
1390 | $('.right-sidebar-collapsed-state').show(); |
|
|||
1391 | $('.right-sidebar-expanded-state').hide(); |
|
|||
1392 |
|
||||
1393 | $sideBar.removeClass('right-sidebar-expanded') |
|
|||
1394 | $sideBar.addClass('right-sidebar-collapsed') |
|
|||
1395 | } |
|
|||
1396 |
|
||||
1397 | toggleSidebar = function () { |
|
|||
1398 | var $sideBar = $('.right-sidebar'); |
|
|||
1399 |
|
||||
1400 | if ($sideBar.hasClass('right-sidebar-expanded')) { |
|
|||
1401 | // expanded -> collapsed transition |
|
|||
1402 | collapseSidebar(); |
|
|||
1403 | var sidebarState = 'collapsed'; |
|
|||
1404 |
|
||||
1405 | } else { |
|
|||
1406 | // collapsed -> expanded |
|
|||
1407 | expandSidebar(); |
|
|||
1408 | var sidebarState = 'expanded'; |
|
|||
1409 | } |
|
|||
1410 |
|
||||
1411 | // update our other sticky header in same context |
|
|||
1412 | updateStickyHeader(); |
|
|||
1413 | storeUserSessionAttr('rc_user_session_attr.sidebarState', sidebarState); |
|
|||
1414 | } |
|
|||
1415 |
|
||||
1416 | var expanded = $sideBar.hasClass('right-sidebar-expanded'); |
|
|||
1417 |
|
||||
1418 | if (templateContext.session_attrs.sidebarState === 'expanded') { |
|
|||
1419 | expanded = true |
|
|||
1420 | } else if (templateContext.session_attrs.sidebarState === 'collapsed') { |
|
|||
1421 | expanded = false |
|
|||
1422 | } |
|
|||
1423 |
|
||||
1424 | // show sidebar since it's hidden on load |
|
|||
1425 | $('.right-sidebar').show(); |
|
|||
1426 |
|
||||
1427 | // init based on set initial class, or if defined user session attrs |
|
|||
1428 | if (expanded) { |
|
|||
1429 | expandSidebar(); |
|
|||
1430 | updateStickyHeader(); |
|
|||
1431 |
|
||||
1432 | } else { |
|
|||
1433 | collapseSidebar(); |
|
|||
1434 | updateStickyHeader(); |
|
|||
1435 | } |
|
|||
1436 |
|
|
987 | var channel = '${c.pr_broadcast_channel}'; | |
1437 |
|
|
988 | new ReviewerPresenceController(channel) | |
1438 |
|
989 | |||
1439 | }) |
|
990 | }) | |
1440 |
|
|
991 | </script> |
General Comments 0
You need to be logged in to leave comments.
Login now