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 | 487 | def assert_comment_links(response, comments, inline_comments): |
|
488 | if comments == 1: | |
|
489 | comments_text = "%d General" % comments | |
|
490 | else: | |
|
491 | comments_text = "%d General" % 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 | |
|
488 | response.mustcontain( | |
|
489 | '<span class="display-none" id="general-comments-count">{}</span>'.format(comments)) | |
|
490 | response.mustcontain( | |
|
491 | '<span class="display-none" id="inline-comments-count">{}</span>'.format(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: | |
|
504 | response.mustcontain( | |
|
505 | 'id="inline-comments-counter">%s' % inline_comments_text) | |
|
506 | else: | |
|
507 | response.mustcontain(inline_comments_text) | |
|
494 |
@@ -18,8 +18,8 b'' | |||
|
18 | 18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 20 | |
|
21 | ||
|
22 | 21 | import logging |
|
22 | import collections | |
|
23 | 23 | |
|
24 | 24 | from pyramid.httpexceptions import ( |
|
25 | 25 | HTTPNotFound, HTTPBadRequest, HTTPFound, HTTPForbidden, HTTPConflict) |
@@ -34,14 +34,14 b' from rhodecode.apps.file_store.exception' | |||
|
34 | 34 | from rhodecode.lib import diffs, codeblocks |
|
35 | 35 | from rhodecode.lib.auth import ( |
|
36 | 36 | LoginRequired, HasRepoPermissionAnyDecorator, NotAnonymous, CSRFRequired) |
|
37 | ||
|
37 | from rhodecode.lib.ext_json import json | |
|
38 | 38 | from rhodecode.lib.compat import OrderedDict |
|
39 | 39 | from rhodecode.lib.diffs import ( |
|
40 | 40 | cache_diff, load_cached_diff, diff_cache_exist, get_diff_context, |
|
41 | 41 | get_diff_whitespace_flag) |
|
42 | 42 | from rhodecode.lib.exceptions import StatusChangeOnClosedPullRequestError, CommentVersionMismatch |
|
43 | 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 | 45 | from rhodecode.lib.vcs.backends.base import EmptyCommit |
|
46 | 46 | from rhodecode.lib.vcs.exceptions import ( |
|
47 | 47 | RepositoryError, CommitDoesNotExistError) |
@@ -87,7 +87,6 b' class RepoCommitsView(RepoAppView):' | |||
|
87 | 87 | diff_limit = c.visual.cut_off_limit_diff |
|
88 | 88 | file_limit = c.visual.cut_off_limit_file |
|
89 | 89 | |
|
90 | ||
|
91 | 90 | # get ranges of commit ids if preset |
|
92 | 91 | commit_range = commit_id_range.split('...')[:2] |
|
93 | 92 | |
@@ -116,6 +115,7 b' class RepoCommitsView(RepoAppView):' | |||
|
116 | 115 | except Exception: |
|
117 | 116 | log.exception("General failure") |
|
118 | 117 | raise HTTPNotFound() |
|
118 | single_commit = len(c.commit_ranges) == 1 | |
|
119 | 119 | |
|
120 | 120 | c.changes = OrderedDict() |
|
121 | 121 | c.lines_added = 0 |
@@ -129,23 +129,48 b' class RepoCommitsView(RepoAppView):' | |||
|
129 | 129 | c.inline_comments = [] |
|
130 | 130 | c.files = [] |
|
131 | 131 | |
|
132 | c.statuses = [] | |
|
133 | 132 | c.comments = [] |
|
134 | 133 | c.unresolved_comments = [] |
|
135 | 134 | c.resolved_comments = [] |
|
136 | if len(c.commit_ranges) == 1: | |
|
135 | ||
|
136 | # Single commit | |
|
137 | if single_commit: | |
|
137 | 138 | commit = c.commit_ranges[0] |
|
138 | 139 | c.comments = CommentsModel().get_comments( |
|
139 | 140 | self.db_repo.repo_id, |
|
140 | 141 | revision=commit.raw_id) |
|
141 | c.statuses.append(ChangesetStatusModel().get_status( | |
|
142 | self.db_repo.repo_id, commit.raw_id)) | |
|
142 | ||
|
143 | 143 | # comments from PR |
|
144 | 144 | statuses = ChangesetStatusModel().get_statuses( |
|
145 | 145 | self.db_repo.repo_id, commit.raw_id, |
|
146 | 146 | with_revisions=True) |
|
147 | prs = set(st.pull_request for st in statuses | |
|
148 | if st.pull_request is not None) | |
|
147 | ||
|
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 | 174 | # from associated statuses, check the pull requests, and |
|
150 | 175 | # show comments from them |
|
151 | 176 | for pr in prs: |
@@ -156,6 +181,37 b' class RepoCommitsView(RepoAppView):' | |||
|
156 | 181 | c.resolved_comments = CommentsModel()\ |
|
157 | 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 | 215 | diff = None |
|
160 | 216 | # Iterate over ranges (default commit view is always one commit) |
|
161 | 217 | for commit in c.commit_ranges: |
@@ -397,6 +453,7 b' class RepoCommitsView(RepoAppView):' | |||
|
397 | 453 | } |
|
398 | 454 | if comment: |
|
399 | 455 | c.co = comment |
|
456 | c.at_version_num = 0 | |
|
400 | 457 | rendered_comment = render( |
|
401 | 458 | 'rhodecode:templates/changeset/changeset_comment_block.mako', |
|
402 | 459 | self._get_template_context(c), self.request) |
@@ -39,7 +39,7 b' from rhodecode.lib.ext_json import json' | |||
|
39 | 39 | from rhodecode.lib.auth import ( |
|
40 | 40 | LoginRequired, HasRepoPermissionAny, HasRepoPermissionAnyDecorator, |
|
41 | 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 | 43 | from rhodecode.lib.vcs.backends.base import EmptyCommit, UpdateFailureReason |
|
44 | 44 | from rhodecode.lib.vcs.exceptions import ( |
|
45 | 45 | CommitDoesNotExistError, RepositoryRequirementError, EmptyRepositoryError) |
@@ -474,9 +474,6 b' class RepoPullRequestsView(RepoAppView, ' | |||
|
474 | 474 | |
|
475 | 475 | c.pull_request_set_reviewers_data_json = json.dumps(c.pull_request_set_reviewers_data_json) |
|
476 | 476 | |
|
477 | ||
|
478 | ||
|
479 | ||
|
480 | 477 | general_comments, inline_comments = \ |
|
481 | 478 | self.register_comments_vars(c, pull_request_latest, versions) |
|
482 | 479 | |
@@ -980,7 +977,7 b' class RepoPullRequestsView(RepoAppView, ' | |||
|
980 | 977 | version = self.request.GET.get('version') |
|
981 | 978 | |
|
982 | 979 | _render = self.request.get_partial_renderer( |
|
983 |
'rhodecode:templates/ |
|
|
980 | 'rhodecode:templates/base/sidebar.mako') | |
|
984 | 981 | c = _render.get_call_context() |
|
985 | 982 | |
|
986 | 983 | (pull_request_latest, |
@@ -999,7 +996,11 b' class RepoPullRequestsView(RepoAppView, ' | |||
|
999 | 996 | |
|
1000 | 997 | self.register_comments_vars(c, pull_request_latest, versions) |
|
1001 | 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 | 1005 | @LoginRequired() |
|
1005 | 1006 | @NotAnonymous() |
@@ -1017,7 +1018,7 b' class RepoPullRequestsView(RepoAppView, ' | |||
|
1017 | 1018 | version = self.request.GET.get('version') |
|
1018 | 1019 | |
|
1019 | 1020 | _render = self.request.get_partial_renderer( |
|
1020 |
'rhodecode:templates/ |
|
|
1021 | 'rhodecode:templates/base/sidebar.mako') | |
|
1021 | 1022 | c = _render.get_call_context() |
|
1022 | 1023 | (pull_request_latest, |
|
1023 | 1024 | pull_request_at_ver, |
@@ -1039,7 +1040,10 b' class RepoPullRequestsView(RepoAppView, ' | |||
|
1039 | 1040 | .get_pull_request_resolved_todos(pull_request) |
|
1040 | 1041 | |
|
1041 | 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 | 1048 | @LoginRequired() |
|
1045 | 1049 | @NotAnonymous() |
@@ -354,34 +354,37 b' class ChangesetStatusModel(BaseModel):' | |||
|
354 | 354 | Session().add(new_status) |
|
355 | 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 | 381 | def reviewers_statuses(self, pull_request): |
|
358 | 382 | _commit_statuses = self.get_statuses( |
|
359 | 383 | pull_request.source_repo, |
|
360 | 384 | pull_request=pull_request, |
|
361 | 385 | with_revisions=True) |
|
362 | 386 | |
|
363 | commit_statuses = collections.defaultdict(list) | |
|
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 | |
|
387 | return self.aggregate_votes_by_user(_commit_statuses, pull_request.reviewers) | |
|
385 | 388 | |
|
386 | 389 | def calculated_review_status(self, pull_request, reviewers_statuses=None): |
|
387 | 390 | """ |
@@ -228,6 +228,14 b' class CommentsModel(BaseModel):' | |||
|
228 | 228 | |
|
229 | 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 | 239 | def _log_audit_action(self, action, action_data, auth_user, comment): |
|
232 | 240 | audit_logger.store( |
|
233 | 241 | action=action, |
@@ -55,3 +55,16 b'' | |||
|
55 | 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 | 255 | .btn-group-actions { |
|
256 | 256 | position: relative; |
|
257 |
z-index: |
|
|
257 | z-index: 50; | |
|
258 | 258 | |
|
259 | 259 | &:not(.open) .btn-action-switcher-container { |
|
260 | 260 | display: none; |
@@ -1078,10 +1078,16 b' input.filediff-collapse-state {' | |||
|
1078 | 1078 | background: @color5; |
|
1079 | 1079 | color: white; |
|
1080 | 1080 | } |
|
1081 | ||
|
1081 | 1082 | &[op="comments"] { /* comments on file */ |
|
1082 | 1083 | background: @grey4; |
|
1083 | 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 | 31 | clear: both; |
|
32 | 32 | } |
|
33 | 33 | |
|
34 | .display-none { | |
|
35 | display: none; | |
|
36 | } | |
|
37 | ||
|
34 | 38 | .pull-right { |
|
35 | 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 | 91 | .action-link{ |
|
87 | 92 | margin-left: @padding; |
|
88 | 93 | padding-left: @padding; |
@@ -482,6 +487,15 b' ul.auth_plugins {' | |||
|
482 | 487 | text-align: left; |
|
483 | 488 | overflow: hidden; |
|
484 | 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 | 501 | .pr-details-title-author-pref { |
@@ -1169,9 +1183,12 b' label {' | |||
|
1169 | 1183 | a { |
|
1170 | 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 | 1189 | display: none; |
|
1174 | 1190 | } |
|
1191 | ||
|
1175 | 1192 | } |
|
1176 | 1193 | |
|
1177 | 1194 | img { |
@@ -1553,6 +1570,7 b' table.integrations {' | |||
|
1553 | 1570 | width: 16px; |
|
1554 | 1571 | padding: 0; |
|
1555 | 1572 | color: black; |
|
1573 | cursor: pointer; | |
|
1556 | 1574 | } |
|
1557 | 1575 | |
|
1558 | 1576 | .reviewer_member_mandatory_remove { |
@@ -1682,7 +1700,7 b' table.group_members {' | |||
|
1682 | 1700 | } |
|
1683 | 1701 | |
|
1684 | 1702 | .reviewer_ac .ac-input { |
|
1685 |
width: |
|
|
1703 | width: 100%; | |
|
1686 | 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 | 2776 | #help_kb .modal-content{ |
|
2759 |
max-width: |
|
|
2777 | max-width: 800px; | |
|
2760 | 2778 | margin: 10% auto; |
|
2761 | 2779 | |
|
2762 | 2780 | table{ |
@@ -3053,4 +3071,141 b' form.markup-form {' | |||
|
3053 | 3071 | |
|
3054 | 3072 | .pr-hovercard-title { |
|
3055 | 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 | 791 | &.main_filter_input { |
|
792 | 792 | padding: 5px 10px; |
|
793 | min-width: 340px; | |
|
793 | ||
|
794 | 794 | color: @grey7; |
|
795 | 795 | background: @black; |
|
796 | 796 | min-height: 18px; |
@@ -800,11 +800,34 b' input {' | |||
|
800 | 800 | color: @grey2 !important; |
|
801 | 801 | background: white !important; |
|
802 | 802 | } |
|
803 | ||
|
803 | 804 | &:focus { |
|
804 | 805 | color: @grey2 !important; |
|
805 | 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 | 168 | .icon-remove:before { content: '\e810'; } /* 'ξ ' */ |
|
169 | 169 | .icon-fork:before { content: '\e811'; } /* 'ξ ' */ |
|
170 | 170 | .icon-more:before { content: '\e812'; } /* 'ξ ' */ |
|
171 | .icon-options:before { content: '\e812'; } /* 'ξ ' */ | |
|
171 | 172 | .icon-search:before { content: '\e813'; } /* 'ξ ' */ |
|
172 | 173 | .icon-scissors:before { content: '\e814'; } /* 'ξ ' */ |
|
173 | 174 | .icon-download:before { content: '\e815'; } /* 'ξ ' */ |
@@ -251,6 +252,7 b'' | |||
|
251 | 252 | // TRANSFORM |
|
252 | 253 | .icon-merge:before {transform: rotate(180deg);} |
|
253 | 254 | .icon-wide-mode:before {transform: rotate(90deg);} |
|
255 | .icon-options:before {transform: rotate(90deg);} | |
|
254 | 256 | |
|
255 | 257 | // -- END ICON CLASSES -- // |
|
256 | 258 |
@@ -131,6 +131,11 b' function setRCMouseBindings(repoName, re' | |||
|
131 | 131 | window.location = pyroutes.url( |
|
132 | 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 | 35 | }, function() { |
|
36 | 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 | 279 | $('#user').show(); // show user autocomplete after load |
|
280 | 280 | |
|
281 | 281 | var commitElements = data["diff_info"]['commits']; |
|
282 | ||
|
282 | 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 | 288 | } else { |
|
286 | 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 | 329 | this.addReviewMember = function (reviewer_obj, reasons, mandatory) { |
|
327 | var members = self.$reviewMembers.get(0); | |
|
328 | 330 | var id = reviewer_obj.user_id; |
|
329 | 331 | var username = reviewer_obj.username; |
|
330 | 332 | |
@@ -333,10 +335,10 b' ReviewersController = function () {' | |||
|
333 | 335 | |
|
334 | 336 | // register IDS to check if we don't have this ID already in |
|
335 | 337 | var currentIds = []; |
|
336 | var _els = self.$reviewMembers.find('li').toArray(); | |
|
337 | for (el in _els) { | |
|
338 |
currentIds.push( |
|
|
339 | } | |
|
338 | ||
|
339 | $.each(self.$reviewMembers.find('.reviewer_entry'), function (index, value) { | |
|
340 | currentIds.push($(value).data('reviewerUserId')) | |
|
341 | }) | |
|
340 | 342 | |
|
341 | 343 | var userAllowedReview = function (userId) { |
|
342 | 344 | var allowed = true; |
@@ -354,12 +356,12 b' ReviewersController = function () {' | |||
|
354 | 356 | alert(_gettext('User `{0}` not allowed to be a reviewer').format(username)); |
|
355 | 357 | } else { |
|
356 | 358 | // only add if it's not there |
|
357 |
var alreadyReviewer = currentIds.indexOf( |
|
|
359 | var alreadyReviewer = currentIds.indexOf(id) != -1; | |
|
358 | 360 | |
|
359 | 361 | if (alreadyReviewer) { |
|
360 | 362 | alert(_gettext('User `{0}` already in reviewers').format(username)); |
|
361 | 363 | } else { |
|
362 |
|
|
|
364 | var reviewerEntry = renderTemplate('reviewMemberEntry', { | |
|
363 | 365 | 'member': reviewer_obj, |
|
364 | 366 | 'mandatory': mandatory, |
|
365 | 367 | 'reasons': reasons, |
@@ -368,7 +370,9 b' ReviewersController = function () {' | |||
|
368 | 370 | 'review_status_label': _gettext('Not Reviewed'), |
|
369 | 371 | 'user_group': reviewer_obj.user_group, |
|
370 | 372 | 'create': true, |
|
371 | }); | |
|
373 | 'rule_show': true, | |
|
374 | }) | |
|
375 | $(self.$reviewMembers.selector).append(reviewerEntry); | |
|
372 | 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 | 500 | var self = this; |
|
497 | 501 | this.$verSource = $('input[name=ver_source]'); |
|
498 | 502 | this.$verTarget = $('input[name=ver_target]'); |
@@ -612,25 +616,10 b' VersionController = function () {' | |||
|
612 | 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 | 623 | var self = this; |
|
635 | 624 | this.$updateCommits = $('#update_commits'); |
|
636 | 625 | this.$updateCommitsSwitcher = $('#update_commits_switcher'); |
@@ -672,4 +661,230 b' UpdatePrController = function () {' | |||
|
672 | 661 | templateContext.repo_name, |
|
673 | 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 | 701 | notice_messages, notice_level = c.rhodecode_user.get_notice_messages() |
|
702 | 702 | notice_display = 'none' if len(notice_messages) == 0 else '' |
|
703 | 703 | %> |
|
704 | <style> | |
|
705 | ||
|
706 | </style> | |
|
707 | 704 | |
|
708 | 705 | <ul id="quick" class="main_nav navigation horizontal-list"> |
|
709 | 706 | ## notice box for important system messages |
@@ -1202,6 +1199,7 b'' | |||
|
1202 | 1199 | ('g p', 'Goto pull requests page'), |
|
1203 | 1200 | ('g o', 'Goto repository settings'), |
|
1204 | 1201 | ('g O', 'Goto repository access permissions settings'), |
|
1202 | ('t s', 'Toggle sidebar on some pages'), | |
|
1205 | 1203 | ] |
|
1206 | 1204 | %> |
|
1207 | 1205 | %for key, desc in elems: |
@@ -1221,3 +1219,36 b'' | |||
|
1221 | 1219 | </div><!-- /.modal-content --> |
|
1222 | 1220 | </div><!-- /.modal-dialog --> |
|
1223 | 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 | 4 | <%namespace name="base" file="/base/base.mako"/> |
|
5 | 5 | <%namespace name="diff_block" file="/changeset/diff_block.mako"/> |
|
6 | 6 | <%namespace name="file_base" file="/files/base.mako"/> |
|
7 | <%namespace name="sidebar" file="/base/sidebar.mako"/> | |
|
8 | ||
|
7 | 9 | |
|
8 | 10 | <%def name="title()"> |
|
9 | 11 | ${_('{} Commit').format(c.repo_name)} - ${h.show_id(c.commit)} |
@@ -100,22 +102,6 b'' | |||
|
100 | 102 | % endif |
|
101 | 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 | 105 | <span id="parent_link" class="tag tagtag"> |
|
120 | 106 | <a href="#parentCommit" title="${_('Parent Commit')}"><i class="icon-left icon-no-margin"></i>${_('parent')}</a> |
|
121 | 107 | </span> |
@@ -123,7 +109,9 b'' | |||
|
123 | 109 | <span id="child_link" class="tag tagtag"> |
|
124 | 110 | <a href="#childCommit" title="${_('Child Commit')}">${_('child')}<i class="icon-right icon-no-margin"></i></a> |
|
125 | 111 | </span> |
|
112 | ||
|
126 | 113 | </div> |
|
114 | ||
|
127 | 115 | </div> |
|
128 | 116 | </div> |
|
129 | 117 | |
@@ -160,7 +148,9 b'' | |||
|
160 | 148 | <%namespace name="cbdiffs" file="/codeblocks/diffs.mako"/> |
|
161 | 149 | ${cbdiffs.render_diffset_menu(c.changes[c.commit.raw_id], commit=c.commit)} |
|
162 | 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 | 154 | </div> |
|
165 | 155 | |
|
166 | 156 | ## template for inline comment form |
@@ -169,7 +159,7 b'' | |||
|
169 | 159 | ## comments heading with count |
|
170 | 160 | <div class="comments-heading"> |
|
171 | 161 | <i class="icon-comment"></i> |
|
172 | ${_('Comments')} ${len(c.comments)} | |
|
162 | ${_('General Comments')} ${len(c.comments)} | |
|
173 | 163 | </div> |
|
174 | 164 | |
|
175 | 165 | ## render comments |
@@ -180,12 +170,130 b'' | |||
|
180 | 170 | h.commit_status(c.rhodecode_db_repo, c.commit.raw_id))} |
|
181 | 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 |
|
|
184 | 291 |
|
|
292 | window.setReviewersData = ${c.commit_set_reviewers_data_json | n}; | |
|
185 | 293 | |
|
186 | 294 |
|
|
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 |
|
|
190 | 298 |
|
|
191 | 299 |
|
@@ -225,9 +333,11 b'' | |||
|
225 | 333 | } |
|
226 | 334 | if(data.results.length === 1){ |
|
227 | 335 | var commit = data.results[0]; |
|
228 |
window.location = pyroutes.url('repo_commit', { |
|
|
229 | } | |
|
230 | else if(data.results.length === 2){ | |
|
336 | window.location = pyroutes.url('repo_commit', { | |
|
337 | 'repo_name': '${c.repo_name}', | |
|
338 | 'commit_id': commit.raw_id | |
|
339 | }); | |
|
340 | } else if (data.results.length === 2) { | |
|
231 | 341 | $('#child_link').addClass('disabled'); |
|
232 | 342 | $('#child_link').addClass('double'); |
|
233 | 343 | |
@@ -236,13 +346,19 b'' | |||
|
236 | 346 | .replace('__branch__', data.results[0].branch) |
|
237 | 347 | .replace('__rev__','r{0}:{1}'.format(data.results[0].revision, data.results[0].raw_id.substr(0,6))) |
|
238 | 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 | 353 | _html +=' | '; |
|
241 | 354 | _html +='<a title="__title__" href="__url__"><span class="tag branchtag"><i class="icon-code-fork"></i>__branch__</span> __rev__</a> ' |
|
242 | 355 | .replace('__branch__', data.results[1].branch) |
|
243 | 356 | .replace('__rev__','r{0}:{1}'.format(data.results[1].revision, data.results[1].raw_id.substr(0,6))) |
|
244 | 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 | 362 | $('#child_link').html(_html); |
|
247 | 363 | } |
|
248 | 364 | } |
@@ -264,9 +380,11 b'' | |||
|
264 | 380 | } |
|
265 | 381 | if(data.results.length === 1){ |
|
266 | 382 | var commit = data.results[0]; |
|
267 |
window.location = pyroutes.url('repo_commit', { |
|
|
268 | } | |
|
269 | else if(data.results.length === 2){ | |
|
383 | window.location = pyroutes.url('repo_commit', { | |
|
384 | 'repo_name': '${c.repo_name}', | |
|
385 | 'commit_id': commit.raw_id | |
|
386 | }); | |
|
387 | } else if (data.results.length === 2) { | |
|
270 | 388 | $('#parent_link').addClass('disabled'); |
|
271 | 389 | $('#parent_link').addClass('double'); |
|
272 | 390 | |
@@ -275,13 +393,19 b'' | |||
|
275 | 393 | .replace('__branch__', data.results[0].branch) |
|
276 | 394 | .replace('__rev__','r{0}:{1}'.format(data.results[0].revision, data.results[0].raw_id.substr(0,6))) |
|
277 | 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 | 400 | _html +=' | '; |
|
280 | 401 | _html +='<a title="__title__" href="__url__"><span class="tag branchtag"><i class="icon-code-fork"></i>__branch__</span> __rev__</a>' |
|
281 | 402 | .replace('__branch__', data.results[1].branch) |
|
282 | 403 | .replace('__rev__','r{0}:{1}'.format(data.results[1].revision, data.results[1].raw_id.substr(0,6))) |
|
283 | 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 | 409 | $('#parent_link').html(_html); |
|
286 | 410 | } |
|
287 | 411 | } |
@@ -296,6 +420,11 b'' | |||
|
296 | 420 |
|
|
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 |
|
|
301 | 430 |
@@ -11,6 +11,10 b'' | |||
|
11 | 11 | <%namespace name="base" file="/base/base.mako"/> |
|
12 | 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 | 18 | <% comment_ver = comment.get_index_version(getattr(c, 'versions', [])) %> |
|
15 | 19 | <% latest_ver = len(getattr(c, 'versions', [])) %> |
|
16 | 20 | |
@@ -155,20 +159,16 b'' | |||
|
155 | 159 | </div> |
|
156 | 160 | %endif |
|
157 | 161 | |
|
158 | <a class="permalink" href="#comment-${comment.comment_id}">¶ #${comment.comment_id}</a> | |
|
159 | ||
|
160 | 162 | <div class="comment-links-block"> |
|
161 | 163 | |
|
162 | 164 | % if inline: |
|
163 | 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 | 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)}"> | |
|
166 | outdated ${'v{}'.format(comment_ver)} | | |
|
167 | </code> | |
|
167 | <code class="tooltip pr-version-num" title="${_('Outdated comment from pull request version v{0}, latest v{1}').format(comment_ver, latest_ver)}">outdated ${'v{}'.format(comment_ver)}</code> | |
|
168 | <code class="action-divider">|</code> | |
|
168 | 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 | ${'v{}'.format(comment_ver)} | | |
|
171 | </code> | |
|
170 | <code class="tooltip pr-version-num" title="${_('Comment from pull request version v{0}, latest v{1}').format(comment_ver, latest_ver)}">${'v{}'.format(comment_ver)}</code> | |
|
171 | <code class="action-divider">|</code> | |
|
172 | 172 | % endif |
|
173 | 173 | </a> |
|
174 | 174 | % else: |
@@ -179,45 +179,70 b'' | |||
|
179 | 179 | href="?version=${comment.pull_request_version_id}#comment-${comment.comment_id}" |
|
180 | 180 | > |
|
181 | 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 | 184 | % else: |
|
184 | 185 | <a class="tooltip pr-version" |
|
185 | 186 | title="${_('Comment from pull request version v{0}, latest v{1}').format(comment_ver, latest_ver)}" |
|
186 | 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 | ${'v{}'.format(comment_ver)} | |
|
190 | </code> | |
|
191 | </a> | | |
|
189 | <code class="pr-version-num">${'v{}'.format(comment_ver)}</code> | |
|
190 | </a> | |
|
191 | <code class="action-divider">|</code> | |
|
192 | 192 | % endif |
|
193 | 193 | |
|
194 | 194 | % endif |
|
195 | 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 | 206 | ## show delete comment if it's not a PR (regular comments) or it's PR that is not closed |
|
198 | 207 | ## only super-admin, repo admin OR comment owner can delete, also hide delete if currently viewed comment is outdated |
|
199 | 208 | %if not outdated_at_ver and (not comment.pull_request or (comment.pull_request and not comment.pull_request.is_closed())): |
|
200 | 209 | ## permissions to delete |
|
201 | 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);" | |
|
203 |
|
|
|
204 |
|
|
|
205 | class="delete-comment">${_('Delete')}</a> | |
|
211 | <div class="dropdown-divider"></div> | |
|
212 | <div class="dropdown-item"> | |
|
213 | <a onclick="return Rhodecode.comments.editComment(this);" class="btn btn-link btn-sm edit-comment">${_('Edit')}</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 | 218 | %else: |
|
219 | <div class="dropdown-divider"></div> | |
|
220 | <div class="dropdown-item"> | |
|
207 | 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 | 226 | %endif |
|
210 | 227 | %else: |
|
228 | <div class="dropdown-divider"></div> | |
|
229 | <div class="dropdown-item"> | |
|
211 | 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 | 235 | %endif |
|
236 | </details-menu> | |
|
237 | </details> | |
|
214 | 238 |
|
|
239 | <code class="action-divider">|</code> | |
|
215 | 240 | % if outdated_at_ver: |
|
216 |
|
|
|
217 |
|
|
|
241 | <a onclick="return Rhodecode.comments.prevOutdatedComment(this);" class="tooltip prev-comment" title="${_('Jump to the previous outdated comment')}"> <i class="icon-angle-left"></i> </a> | |
|
242 | <a onclick="return Rhodecode.comments.nextOutdatedComment(this);" class="tooltip next-comment" title="${_('Jump to the next outdated comment')}"> <i class="icon-angle-right"></i></a> | |
|
218 | 243 | % else: |
|
219 |
|
|
|
220 |
|
|
|
244 | <a onclick="return Rhodecode.comments.prevComment(this);" class="tooltip prev-comment" title="${_('Jump to the previous comment')}"> <i class="icon-angle-left"></i></a> | |
|
245 | <a onclick="return Rhodecode.comments.nextComment(this);" class="tooltip next-comment" title="${_('Jump to the next comment')}"> <i class="icon-angle-right"></i></a> | |
|
221 | 246 | % endif |
|
222 | 247 | |
|
223 | 248 | </div> |
@@ -102,6 +102,11 b'' | |||
|
102 | 102 | <%namespace name="diff_block" file="/changeset/diff_block.mako"/> |
|
103 | 103 | |
|
104 | 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 | 110 | ${cbdiffs.render_diffset_menu(c.changes[commit.raw_id])} |
|
106 | 111 | ${cbdiffs.render_diffset( |
|
107 | 112 | diffset=c.changes[commit.raw_id], |
@@ -61,6 +61,8 b" return '%s_%s_%i' % (h.md5_safe(commit+f" | |||
|
61 | 61 | diffset_container_id = h.md5(diffset.target_ref) |
|
62 | 62 | collapse_all = len(diffset.files) > collapse_when_files_over |
|
63 | 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 | 68 | %if use_comments: |
@@ -208,13 +210,6 b" return '%s_%s_%i' % (h.md5_safe(commit+f" | |||
|
208 | 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 | 211 | </h2> |
|
210 | 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 | 213 | % endif |
|
219 | 214 | |
|
220 | 215 | <div id="todo-box"> |
@@ -239,6 +234,43 b" return '%s_%s_%i' % (h.md5_safe(commit+f" | |||
|
239 | 234 | <% over_lines_changed_limit = False %> |
|
240 | 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 | 275 | lines_changed = filediff.patch['stats']['added'] + filediff.patch['stats']['deleted'] |
|
244 | 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 | 290 | total_file_comments = [_c for _c in h.itertools.chain.from_iterable(file_comments) if not _c.outdated] |
|
259 | 291 | %> |
|
260 | 292 | <div class="filediff-collapse-indicator icon-"></div> |
|
293 | ||
|
294 | ## Comments/Options PILL | |
|
261 | 295 |
<span class="pill-group pull-right" |
|
262 | 296 | <span class="pill" op="comments"> |
|
263 | ||
|
264 | 297 | <i class="icon-comment"></i> ${len(total_file_comments)} |
|
265 | 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 | 323 | </span> |
|
267 | ${diff_ops(filediff)} | |
|
324 | ||
|
325 | ${diff_ops(final_file_name, filediff)} | |
|
268 | 326 | |
|
269 | 327 | </label> |
|
270 | 328 | |
@@ -463,43 +521,15 b" return '%s_%s_%i' % (h.md5_safe(commit+f" | |||
|
463 | 521 | </div> |
|
464 | 522 | </%def> |
|
465 | 523 | |
|
466 | <%def name="diff_ops(filediff)"> | |
|
524 | <%def name="diff_ops(file_name, filediff)"> | |
|
467 | 525 | <% |
|
468 | 526 | from rhodecode.lib.diffs import NEW_FILENODE, DEL_FILENODE, \ |
|
469 | 527 | MOD_FILENODE, RENAMED_FILENODE, CHMOD_FILENODE, BIN_FILENODE, COPIED_FILENODE |
|
470 | 528 | %> |
|
471 | 529 | <span class="pill"> |
|
472 | 530 | <i class="icon-file-text"></i> |
|
473 | %if filediff.source_file_path and filediff.target_file_path: | |
|
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> | |
|
531 | ${file_name} | |
|
500 | 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 | 534 | <span class="pill-group pull-right"> |
|
505 | 535 |
@@ -53,6 +53,14 b" var data_hovercard_url = pyroutes.url('h" | |||
|
53 | 53 | var reviewGroup = null; |
|
54 | 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 | 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 | 106 | </td> |
|
99 | 107 | |
|
100 | 108 | <% } else { %> |
|
101 | <td> | |
|
109 | <td style="text-align: right;width: 10px;"> | |
|
102 | 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 | 112 | <i class="icon-remove"></i> |
|
105 | 113 | </div> |
|
106 | 114 | <% } %> |
@@ -110,7 +118,7 b" var data_hovercard_url = pyroutes.url('h" | |||
|
110 | 118 | </tr> |
|
111 | 119 | |
|
112 | 120 | <tr> |
|
113 |
<td colspan="4" style="display: |
|
|
121 | <td colspan="4" style="display: <%= rule_visibility %>" class="pr-user-rule-container"> | |
|
114 | 122 | <input type="hidden" name="__start__" value="reviewer:mapping"> |
|
115 | 123 | |
|
116 | 124 | <%if (member.user_group && member.user_group.vote_rule) { %> |
@@ -19,20 +19,73 b'' | |||
|
19 | 19 | <div class="box"> |
|
20 | 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 | 24 | <div class="summary-details block-left"> |
|
25 | 25 | |
|
26 | ||
|
27 | <div class="pr-details-title"> | |
|
28 | ${_('New pull request')} | |
|
29 | </div> | |
|
30 | ||
|
31 | 26 | <div class="form" style="padding-top: 10px"> |
|
32 | <!-- fields --> | |
|
33 | 27 | |
|
34 | 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 |
|
|
37 | 90 | <div class="label"> |
|
38 | 91 | <label for="pullrequest_title">${_('Title')}:</label> |
@@ -45,6 +98,7 b'' | |||
|
45 | 98 | </p> |
|
46 | 99 |
|
|
47 | 100 | |
|
101 | ## DESC | |
|
48 | 102 | <div class="field"> |
|
49 | 103 | <div class="label label-textarea"> |
|
50 | 104 | <label for="pullrequest_desc">${_('Description')}:</label> |
@@ -55,72 +109,14 b'' | |||
|
55 | 109 | </div> |
|
56 | 110 | </div> |
|
57 | 111 | |
|
112 | ## REVIEWERS | |
|
58 | 113 | <div class="field"> |
|
59 | 114 | <div class="label label-textarea"> |
|
60 |
<label for=" |
|
|
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} | |
|
115 | <label for="pullrequest_reviewers">${_('Reviewers')}:</label> | |
|
70 | 116 | </div> |
|
71 | 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 | 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 | 120 | <div class="pr-details-title"> |
|
125 | 121 | ${_('Reviewer rules')} |
|
126 | 122 | </div> |
@@ -130,32 +126,48 b'' | |||
|
130 | 126 | </div> |
|
131 | 127 | |
|
132 | 128 | ## REVIEWERS |
|
133 |
<div class="reviewers-title |
|
|
129 | <div class="reviewers-title"> | |
|
134 | 130 | <div class="pr-details-title"> |
|
135 | 131 | ${_('Pull request reviewers')} |
|
136 | 132 | <span class="calculate-reviewers"> - ${_('loading...')}</span> |
|
137 | 133 | </div> |
|
138 | 134 | </div> |
|
139 |
<div id="reviewers" class=" |
|
|
135 | <div id="reviewers" class="pr-details-content reviewers"> | |
|
140 | 136 | ## members goes here, filled via JS based on initial selection ! |
|
141 | 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 | 141 | <input type="hidden" name="__end__" value="review_members:sequence"> |
|
142 | ||
|
144 | 143 | <div id="add_reviewer_input" class='ac'> |
|
145 | 144 | <div class="reviewer_ac"> |
|
146 | 145 | ${h.text('user', class_='ac-input', placeholder=_('Add reviewer or reviewer group'))} |
|
147 | 146 | <div id="reviewers_container"></div> |
|
148 | 147 | </div> |
|
149 | 148 | </div> |
|
149 | ||
|
150 | 150 | </div> |
|
151 | 151 | </div> |
|
152 | 152 | </div> |
|
153 | <div class="box"> | |
|
154 | <div> | |
|
155 | ## overview pulled by ajax | |
|
156 | <div id="pull_request_overview"></div> | |
|
153 | ||
|
154 | ## SUBMIT | |
|
155 | <div class="field"> | |
|
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 | 162 | </div> |
|
158 | 163 | </div> |
|
164 | </div> | |
|
165 | </div> | |
|
166 | </div> | |
|
167 | </div> | |
|
168 | ||
|
169 | </div> | |
|
170 | ||
|
159 | 171 | ${h.end_form()} |
|
160 | 172 | </div> |
|
161 | 173 | |
@@ -243,8 +255,6 b'' | |||
|
243 | 255 | |
|
244 | 256 | var diffDataHandler = function(data) { |
|
245 | 257 | |
|
246 | $('#pull_request_overview').html(data); | |
|
247 | ||
|
248 | 258 | var commitElements = data['commits']; |
|
249 | 259 | var files = data['files']; |
|
250 | 260 | var added = data['stats'][0] |
@@ -303,27 +313,33 b'' | |||
|
303 | 313 | |
|
304 | 314 | msg += '<input type="hidden" name="__end__" value="revisions:sequence">' |
|
305 | 315 | msg += _ngettext( |
|
306 |
' |
|
|
307 |
' |
|
|
316 | 'Compare summary: <strong>{0} commit</strong>', | |
|
317 | 'Compare summary: <strong>{0} commits</strong>', | |
|
308 | 318 | commitElements.length).format(commitElements.length) |
|
309 | 319 | |
|
310 |
msg += ' |
|
|
320 | msg += ''; | |
|
311 | 321 | msg += _ngettext( |
|
312 |
'<strong>{0} file</strong> changed |
|
|
313 |
'<strong>{0} files</strong> changed |
|
|
322 | '<strong>, and {0} file</strong> changed.', | |
|
323 | '<strong>, and {0} files</strong> changed.', | |
|
314 | 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 | 330 | if (commitElements.length) { |
|
320 | 331 | var commitsLink = '<a href="#pull_request_overview"><strong>{0}</strong></a>'.format(commitElements.length); |
|
321 | 332 | prButtonLock(false, msg.replace('__COMMITS__', commitsLink), 'compare'); |
|
322 | 333 | } |
|
323 | 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 | 345 | reviewersController = new ReviewersController(); |
@@ -429,10 +445,12 b'' | |||
|
429 | 445 | |
|
430 | 446 | var targetRepoChanged = function(repoData) { |
|
431 | 447 | // generate new DESC of target repo displayed next to select |
|
448 | ||
|
449 | $('#target_repo_desc').html(repoData['description']); | |
|
450 | ||
|
432 | 451 | var prLink = pyroutes.url('pullrequest_new', {'repo_name': repoData['name']}); |
|
433 | $('#target_repo_desc').html( | |
|
434 | "<strong>${_('Target repository')}</strong>: {0}. <a href=\"{1}\">Switch base, and use as source.</a>".format(repoData['description'], prLink) | |
|
435 | ); | |
|
452 | var title = _gettext('Switch target repository with the source.') | |
|
453 | $('#switch_base').html("<a class=\"tooltip\" title=\"{0}\" href=\"{1}\">Switch sides</a>".format(title, prLink)) | |
|
436 | 454 | |
|
437 | 455 | // generate dynamic select2 for refs. |
|
438 | 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 | 1 | <%inherit file="/base/base.mako"/> |
|
2 | 2 | <%namespace name="base" file="/base/base.mako"/> |
|
3 | 3 | <%namespace name="dt" file="/data_table/_dt_elements.mako"/> |
|
4 | <%namespace name="sidebar" file="/base/sidebar.mako"/> | |
|
5 | ||
|
4 | 6 | |
|
5 | 7 | <%def name="title()"> |
|
6 | 8 | ${_('{} Pull Request !{}').format(c.repo_name, c.pull_request.pull_request_id)} |
@@ -21,113 +23,6 b'' | |||
|
21 | 23 | ${self.repo_menu(active='showpullrequest')} |
|
22 | 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 | 27 | <%def name="main()"> |
|
133 | 28 | ## Container to gather extracted Tickets |
@@ -140,6 +35,7 b'' | |||
|
140 | 35 | // TODO: marcink switch this to pyroutes |
|
141 | 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 | 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 | 39 | </script> |
|
144 | 40 | |
|
145 | 41 | <div class="box"> |
@@ -226,7 +122,7 b'' | |||
|
226 | 122 | |
|
227 | 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 | 126 | <i class="icon-angle-down">more details</i> |
|
231 | 127 | </a> |
|
232 | 128 | |
@@ -643,101 +539,12 b'' | |||
|
643 | 539 | </div> |
|
644 | 540 | |
|
645 | 541 | |
|
646 | ### NAVBOG RIGHT | |
|
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 | ||
|
542 | ### NAV SIDEBAR | |
|
736 | 543 | <aside class="right-sidebar right-sidebar-expanded" id="pr-nav-sticky" style="display: none"> |
|
737 | 544 | <div class="sidenav navbar__inner" > |
|
738 | 545 | ## TOGGLE |
|
739 | 546 | <div class="sidebar-toggle" onclick="toggleSidebar(); return false"> |
|
740 | <a href="#toggleSidebar"> | |
|
547 | <a href="#toggleSidebar" class="grey-link-action"> | |
|
741 | 548 | |
|
742 | 549 | </a> |
|
743 | 550 | </div> |
@@ -747,8 +554,12 b'' | |||
|
747 | 554 | |
|
748 | 555 | ## RULES SUMMARY/RULES |
|
749 | 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 | 563 | <i class="icon-circle review-status-${c.pull_request_review_status}"></i> |
|
753 | 564 | ${len(c.allowed_reviewers)} |
|
754 | 565 | </div> |
@@ -769,7 +580,7 b'' | |||
|
769 | 580 | |
|
770 | 581 | ## REVIEWERS |
|
771 | 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 | 584 | <i class="icon-circle review-status-${c.pull_request_review_status}"></i> |
|
774 | 585 | ${_('Reviewers')} |
|
775 | 586 | </span> |
@@ -846,7 +657,7 b'' | |||
|
846 | 657 | |
|
847 | 658 | % if not c.at_version: |
|
848 | 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 | 661 | % else: |
|
851 | 662 | <span class="block-right last-item noselect">Show resolved</span> |
|
852 | 663 | % endif |
@@ -863,7 +674,7 b'' | |||
|
863 | 674 | </table> |
|
864 | 675 | % else: |
|
865 | 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 | 678 | % else: |
|
868 | 679 | <table> |
|
869 | 680 | <tr> |
@@ -882,6 +693,8 b'' | |||
|
882 | 693 | <div class="tooltip right-sidebar-collapsed-state" style="display: none" onclick="toggleSidebar(); return false" title="${_('Comments')}"> |
|
883 | 694 | <i class="icon-comment" style="color: #949494"></i> |
|
884 | 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 | 698 | </div> |
|
886 | 699 | |
|
887 | 700 | <div class="right-sidebar-expanded-state pr-details-title"> |
@@ -903,7 +716,7 b'' | |||
|
903 | 716 | </span> |
|
904 | 717 | |
|
905 | 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 | 720 | % else: |
|
908 | 721 | <span class="block-right last-item noselect">Show hidden</span> |
|
909 | 722 | % endif |
@@ -912,7 +725,7 b'' | |||
|
912 | 725 | |
|
913 | 726 | <div class="right-sidebar-expanded-state pr-details-content"> |
|
914 | 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 | 729 | % else: |
|
917 | 730 | <table> |
|
918 | 731 | <tr> |
@@ -942,7 +755,7 b'' | |||
|
942 | 755 | <div class="right-sidebar-expanded-state pr-details-content"> |
|
943 | 756 | <table> |
|
944 | 757 | |
|
945 |
<tr><td><code>${_(' |
|
|
758 | <tr><td><code>${_('In pull request description')}:</code></td></tr> | |
|
946 | 759 | % if c.referenced_desc_issues: |
|
947 | 760 | % for ticket_dict in c.referenced_desc_issues: |
|
948 | 761 | <tr> |
@@ -961,7 +774,7 b'' | |||
|
961 | 774 | </tr> |
|
962 | 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 | 778 | % if c.referenced_commit_issues: |
|
966 | 779 | % for ticket_dict in c.referenced_commit_issues: |
|
967 | 780 | <tr> |
@@ -1000,63 +813,12 b'' | |||
|
1000 | 813 | |
|
1001 | 814 |
|
|
1002 | 815 | |
|
1003 | /** leak object to top level scope **/ | |
|
1004 | window.PullRequestPresenceController; | |
|
816 | window.reviewerRulesData = ${c.pull_request_default_reviewers_data_json | n}; | |
|
817 | window.setReviewersData = ${c.pull_request_set_reviewers_data_json | n}; | |
|
1005 | 818 | |
|
1006 | 819 | (function () { |
|
1007 | 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 |
|
|
1061 | 823 |
|
|
1062 | 824 | |
@@ -1078,12 +840,13 b' window.PullRequestPresenceController;' | |||
|
1078 | 840 |
|
|
1079 | 841 | |
|
1080 | 842 |
|
|
843 | var cmInstance = $('#pr-description-input').get(0).MarkupForm.cm; | |
|
1081 | 844 |
|
|
1082 | 845 |
|
|
1083 | 846 |
|
|
1084 | 847 |
|
|
1085 | 848 |
|
|
1086 |
|
|
|
849 | cmInstance.refresh(); | |
|
1087 | 850 |
|
|
1088 | 851 | |
|
1089 | 852 |
|
@@ -1095,88 +858,24 b' window.PullRequestPresenceController;' | |||
|
1095 | 858 |
|
|
1096 | 859 |
|
|
1097 | 860 | |
|
1098 | var ReviewersPanel = { | |
|
1099 | editButton: $('#open_edit_reviewers'), | |
|
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; | |
|
861 | PRDetails.init(); | |
|
862 | ReviewersPanel.init(reviewerRulesData, setReviewersData); | |
|
1125 | 863 | |
|
1126 | var entry = renderTemplate('reviewMemberEntry', { | |
|
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) { | |
|
864 | window.showOutdated = function (self) { | |
|
1166 | 865 |
|
|
1167 | 866 |
|
|
1168 | 867 |
|
|
1169 | 868 |
|
|
1170 | 869 |
|
|
1171 | 870 | |
|
1172 |
|
|
|
871 | window.hideOutdated = function (self) { | |
|
1173 | 872 |
|
|
1174 | 873 |
|
|
1175 | 874 |
|
|
1176 | 875 |
|
|
1177 | 876 |
|
|
1178 | 877 | |
|
1179 |
|
|
|
878 | window.refreshMergeChecks = function () { | |
|
1180 | 879 |
|
|
1181 | 880 |
|
|
1182 | 881 |
|
@@ -1190,76 +889,7 b' window.PullRequestPresenceController;' | |||
|
1190 | 889 |
|
|
1191 | 890 |
|
|
1192 | 891 | |
|
1193 | refreshComments = function () { | |
|
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) { | |
|
892 | window.closePullRequest = function (status) { | |
|
1263 | 893 |
|
|
1264 | 894 |
|
|
1265 | 895 |
|
@@ -1269,6 +899,7 b' window.PullRequestPresenceController;' | |||
|
1269 | 899 |
|
|
1270 | 900 |
|
|
1271 | 901 | |
|
902 | //TODO this functionality is now missing | |
|
1272 | 903 |
|
|
1273 | 904 |
|
|
1274 | 905 |
|
@@ -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 |
|
|
1302 | 917 |
|
|
1303 | 918 |
|
@@ -1322,7 +937,6 b' window.PullRequestPresenceController;' | |||
|
1322 | 937 |
|
|
1323 | 938 |
|
|
1324 | 939 | |
|
1325 | ||
|
1326 | 940 |
|
|
1327 | 941 |
|
|
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 |
|
|
1347 | 977 |
|
|
1348 | 978 |
|
@@ -1350,91 +980,12 b' window.PullRequestPresenceController;' | |||
|
1350 | 980 | |
|
1351 | 981 |
|
|
1352 | 982 | |
|
1353 | }) | |
|
983 | })(); | |
|
1354 | 984 | |
|
1355 | 985 |
|
|
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 |
|
|
1437 |
|
|
|
988 | new ReviewerPresenceController(channel) | |
|
1438 | 989 | |
|
1439 | 990 | }) |
|
1440 | 991 |
|
General Comments 0
You need to be logged in to leave comments.
Login now