Show More
@@ -345,6 +345,16 b' def includeme(config):' | |||||
345 | pattern='/{repo_name:.*?[^/]}/pull-request/{pull_request_id:\d+}/comment/{comment_id}/delete', |
|
345 | pattern='/{repo_name:.*?[^/]}/pull-request/{pull_request_id:\d+}/comment/{comment_id}/delete', | |
346 | repo_route=True, repo_accepted_types=['hg', 'git']) |
|
346 | repo_route=True, repo_accepted_types=['hg', 'git']) | |
347 |
|
347 | |||
|
348 | config.add_route( | |||
|
349 | name='pullrequest_comments', | |||
|
350 | pattern='/{repo_name:.*?[^/]}/pull-request/{pull_request_id:\d+}/comments', | |||
|
351 | repo_route=True) | |||
|
352 | ||||
|
353 | config.add_route( | |||
|
354 | name='pullrequest_todos', | |||
|
355 | pattern='/{repo_name:.*?[^/]}/pull-request/{pull_request_id:\d+}/todos', | |||
|
356 | repo_route=True) | |||
|
357 | ||||
348 | # Artifacts, (EE feature) |
|
358 | # Artifacts, (EE feature) | |
349 | config.add_route( |
|
359 | config.add_route( | |
350 | name='repo_artifacts_list', |
|
360 | name='repo_artifacts_list', |
@@ -87,6 +87,7 b' class RepoCommitsView(RepoAppView):' | |||||
87 | diff_limit = c.visual.cut_off_limit_diff |
|
87 | diff_limit = c.visual.cut_off_limit_diff | |
88 | file_limit = c.visual.cut_off_limit_file |
|
88 | file_limit = c.visual.cut_off_limit_file | |
89 |
|
89 | |||
|
90 | ||||
90 | # get ranges of commit ids if preset |
|
91 | # get ranges of commit ids if preset | |
91 | commit_range = commit_id_range.split('...')[:2] |
|
92 | commit_range = commit_id_range.split('...')[:2] | |
92 |
|
93 | |||
@@ -226,6 +227,7 b' class RepoCommitsView(RepoAppView):' | |||||
226 |
|
227 | |||
227 | # sort comments by how they were generated |
|
228 | # sort comments by how they were generated | |
228 | c.comments = sorted(c.comments, key=lambda x: x.comment_id) |
|
229 | c.comments = sorted(c.comments, key=lambda x: x.comment_id) | |
|
230 | c.at_version_num = None | |||
229 |
|
231 | |||
230 | if len(c.commit_ranges) == 1: |
|
232 | if len(c.commit_ranges) == 1: | |
231 | c.commit = c.commit_ranges[0] |
|
233 | c.commit = c.commit_ranges[0] |
@@ -265,6 +265,36 b' class RepoPullRequestsView(RepoAppView, ' | |||||
265 |
|
265 | |||
266 | return diffset |
|
266 | return diffset | |
267 |
|
267 | |||
|
268 | def register_comments_vars(self, c, pull_request, versions): | |||
|
269 | comments_model = CommentsModel() | |||
|
270 | ||||
|
271 | # GENERAL COMMENTS with versions # | |||
|
272 | q = comments_model._all_general_comments_of_pull_request(pull_request) | |||
|
273 | q = q.order_by(ChangesetComment.comment_id.asc()) | |||
|
274 | general_comments = q | |||
|
275 | ||||
|
276 | # pick comments we want to render at current version | |||
|
277 | c.comment_versions = comments_model.aggregate_comments( | |||
|
278 | general_comments, versions, c.at_version_num) | |||
|
279 | ||||
|
280 | # INLINE COMMENTS with versions # | |||
|
281 | q = comments_model._all_inline_comments_of_pull_request(pull_request) | |||
|
282 | q = q.order_by(ChangesetComment.comment_id.asc()) | |||
|
283 | inline_comments = q | |||
|
284 | ||||
|
285 | c.inline_versions = comments_model.aggregate_comments( | |||
|
286 | inline_comments, versions, c.at_version_num, inline=True) | |||
|
287 | ||||
|
288 | # Comments inline+general | |||
|
289 | if c.at_version: | |||
|
290 | c.inline_comments_flat = c.inline_versions[c.at_version_num]['display'] | |||
|
291 | c.comments = c.comment_versions[c.at_version_num]['display'] | |||
|
292 | else: | |||
|
293 | c.inline_comments_flat = c.inline_versions[c.at_version_num]['until'] | |||
|
294 | c.comments = c.comment_versions[c.at_version_num]['until'] | |||
|
295 | ||||
|
296 | return general_comments, inline_comments | |||
|
297 | ||||
268 | @LoginRequired() |
|
298 | @LoginRequired() | |
269 | @HasRepoPermissionAnyDecorator( |
|
299 | @HasRepoPermissionAnyDecorator( | |
270 | 'repository.read', 'repository.write', 'repository.admin') |
|
300 | 'repository.read', 'repository.write', 'repository.admin') | |
@@ -280,6 +310,8 b' class RepoPullRequestsView(RepoAppView, ' | |||||
280 | pull_request_id = pull_request.pull_request_id |
|
310 | pull_request_id = pull_request.pull_request_id | |
281 |
|
311 | |||
282 | c.state_progressing = pull_request.is_state_changing() |
|
312 | c.state_progressing = pull_request.is_state_changing() | |
|
313 | c.pr_broadcast_channel = '/repo${}$/pr/{}'.format( | |||
|
314 | pull_request.target_repo.repo_name, pull_request.pull_request_id) | |||
283 |
|
315 | |||
284 | _new_state = { |
|
316 | _new_state = { | |
285 | 'created': PullRequest.STATE_CREATED, |
|
317 | 'created': PullRequest.STATE_CREATED, | |
@@ -300,22 +332,23 b' class RepoPullRequestsView(RepoAppView, ' | |||||
300 | from_version = self.request.GET.get('from_version') or version |
|
332 | from_version = self.request.GET.get('from_version') or version | |
301 | merge_checks = self.request.GET.get('merge_checks') |
|
333 | merge_checks = self.request.GET.get('merge_checks') | |
302 | c.fulldiff = str2bool(self.request.GET.get('fulldiff')) |
|
334 | c.fulldiff = str2bool(self.request.GET.get('fulldiff')) | |
|
335 | force_refresh = str2bool(self.request.GET.get('force_refresh')) | |||
|
336 | c.range_diff_on = self.request.GET.get('range-diff') == "1" | |||
303 |
|
337 | |||
304 | # fetch global flags of ignore ws or context lines |
|
338 | # fetch global flags of ignore ws or context lines | |
305 | diff_context = diffs.get_diff_context(self.request) |
|
339 | diff_context = diffs.get_diff_context(self.request) | |
306 | hide_whitespace_changes = diffs.get_diff_whitespace_flag(self.request) |
|
340 | hide_whitespace_changes = diffs.get_diff_whitespace_flag(self.request) | |
307 |
|
341 | |||
308 | force_refresh = str2bool(self.request.GET.get('force_refresh')) |
|
|||
309 |
|
||||
310 | (pull_request_latest, |
|
342 | (pull_request_latest, | |
311 | pull_request_at_ver, |
|
343 | pull_request_at_ver, | |
312 | pull_request_display_obj, |
|
344 | pull_request_display_obj, | |
313 | at_version) = PullRequestModel().get_pr_version( |
|
345 | at_version) = PullRequestModel().get_pr_version( | |
314 | pull_request_id, version=version) |
|
346 | pull_request_id, version=version) | |
|
347 | ||||
315 | pr_closed = pull_request_latest.is_closed() |
|
348 | pr_closed = pull_request_latest.is_closed() | |
316 |
|
349 | |||
317 | if pr_closed and (version or from_version): |
|
350 | if pr_closed and (version or from_version): | |
318 | # not allow to browse versions |
|
351 | # not allow to browse versions for closed PR | |
319 | raise HTTPFound(h.route_path( |
|
352 | raise HTTPFound(h.route_path( | |
320 | 'pullrequest_show', repo_name=self.db_repo_name, |
|
353 | 'pullrequest_show', repo_name=self.db_repo_name, | |
321 | pull_request_id=pull_request_id)) |
|
354 | pull_request_id=pull_request_id)) | |
@@ -323,13 +356,13 b' class RepoPullRequestsView(RepoAppView, ' | |||||
323 | versions = pull_request_display_obj.versions() |
|
356 | versions = pull_request_display_obj.versions() | |
324 | # used to store per-commit range diffs |
|
357 | # used to store per-commit range diffs | |
325 | c.changes = collections.OrderedDict() |
|
358 | c.changes = collections.OrderedDict() | |
326 | c.range_diff_on = self.request.GET.get('range-diff') == "1" |
|
|||
327 |
|
359 | |||
328 | c.at_version = at_version |
|
360 | c.at_version = at_version | |
329 | c.at_version_num = (at_version |
|
361 | c.at_version_num = (at_version | |
330 |
if at_version and at_version != |
|
362 | if at_version and at_version != PullRequest.LATEST_VER | |
331 | else None) |
|
363 | else None) | |
332 | c.at_version_pos = ChangesetComment.get_index_from_version( |
|
364 | ||
|
365 | c.at_version_index = ChangesetComment.get_index_from_version( | |||
333 | c.at_version_num, versions) |
|
366 | c.at_version_num, versions) | |
334 |
|
367 | |||
335 | (prev_pull_request_latest, |
|
368 | (prev_pull_request_latest, | |
@@ -340,9 +373,9 b' class RepoPullRequestsView(RepoAppView, ' | |||||
340 |
|
373 | |||
341 | c.from_version = prev_at_version |
|
374 | c.from_version = prev_at_version | |
342 | c.from_version_num = (prev_at_version |
|
375 | c.from_version_num = (prev_at_version | |
343 |
if prev_at_version and prev_at_version != |
|
376 | if prev_at_version and prev_at_version != PullRequest.LATEST_VER | |
344 | else None) |
|
377 | else None) | |
345 |
c.from_version_ |
|
378 | c.from_version_index = ChangesetComment.get_index_from_version( | |
346 | c.from_version_num, versions) |
|
379 | c.from_version_num, versions) | |
347 |
|
380 | |||
348 | # define if we're in COMPARE mode or VIEW at version mode |
|
381 | # define if we're in COMPARE mode or VIEW at version mode | |
@@ -355,14 +388,17 b' class RepoPullRequestsView(RepoAppView, ' | |||||
355 | self.db_repo_name, pull_request_at_ver.target_repo.repo_name) |
|
388 | self.db_repo_name, pull_request_at_ver.target_repo.repo_name) | |
356 | raise HTTPNotFound() |
|
389 | raise HTTPNotFound() | |
357 |
|
390 | |||
358 | c.shadow_clone_url = PullRequestModel().get_shadow_clone_url( |
|
391 | c.shadow_clone_url = PullRequestModel().get_shadow_clone_url(pull_request_at_ver) | |
359 | pull_request_at_ver) |
|
|||
360 |
|
392 | |||
361 | c.pull_request = pull_request_display_obj |
|
393 | c.pull_request = pull_request_display_obj | |
362 | c.renderer = pull_request_at_ver.description_renderer or c.renderer |
|
394 | c.renderer = pull_request_at_ver.description_renderer or c.renderer | |
363 | c.pull_request_latest = pull_request_latest |
|
395 | c.pull_request_latest = pull_request_latest | |
364 |
|
396 | |||
365 | if compare or (at_version and not at_version == 'latest'): |
|
397 | # inject latest version | |
|
398 | latest_ver = PullRequest.get_pr_display_object(pull_request_latest, pull_request_latest) | |||
|
399 | c.versions = versions + [latest_ver] | |||
|
400 | ||||
|
401 | if compare or (at_version and not at_version == PullRequest.LATEST_VER): | |||
366 | c.allowed_to_change_status = False |
|
402 | c.allowed_to_change_status = False | |
367 | c.allowed_to_update = False |
|
403 | c.allowed_to_update = False | |
368 | c.allowed_to_merge = False |
|
404 | c.allowed_to_merge = False | |
@@ -391,12 +427,9 b' class RepoPullRequestsView(RepoAppView, ' | |||||
391 | 'rules' in pull_request_latest.reviewer_data: |
|
427 | 'rules' in pull_request_latest.reviewer_data: | |
392 | rules = pull_request_latest.reviewer_data['rules'] or {} |
|
428 | rules = pull_request_latest.reviewer_data['rules'] or {} | |
393 | try: |
|
429 | try: | |
394 | c.forbid_adding_reviewers = rules.get( |
|
430 | c.forbid_adding_reviewers = rules.get('forbid_adding_reviewers') | |
395 | 'forbid_adding_reviewers') |
|
431 | c.forbid_author_to_review = rules.get('forbid_author_to_review') | |
396 | c.forbid_author_to_review = rules.get( |
|
432 | c.forbid_commit_author_to_review = rules.get('forbid_commit_author_to_review') | |
397 | 'forbid_author_to_review') |
|
|||
398 | c.forbid_commit_author_to_review = rules.get( |
|
|||
399 | 'forbid_commit_author_to_review') |
|
|||
400 | except Exception: |
|
433 | except Exception: | |
401 | pass |
|
434 | pass | |
402 |
|
435 | |||
@@ -421,41 +454,37 b' class RepoPullRequestsView(RepoAppView, ' | |||||
421 | 'rhodecode:templates/pullrequests/pullrequest_merge_checks.mako' |
|
454 | 'rhodecode:templates/pullrequests/pullrequest_merge_checks.mako' | |
422 | return self._get_template_context(c) |
|
455 | return self._get_template_context(c) | |
423 |
|
456 | |||
424 | comments_model = CommentsModel() |
|
457 | c.allowed_reviewers = [obj.user_id for obj in pull_request.reviewers if obj.user] | |
425 |
|
458 | |||
426 | # reviewers and statuses |
|
459 | # reviewers and statuses | |
427 |
c.pull_request_reviewers = |
|
460 | c.pull_request_default_reviewers_data_json = json.dumps(pull_request.reviewer_data) | |
428 | allowed_reviewers = [x[0].user_id for x in c.pull_request_reviewers] |
|
461 | c.pull_request_set_reviewers_data_json = collections.OrderedDict({'reviewers': []}) | |
429 |
|
462 | |||
430 | # GENERAL COMMENTS with versions # |
|
463 | for review_obj, member, reasons, mandatory, status in pull_request_at_ver.reviewers_statuses(): | |
431 | q = comments_model._all_general_comments_of_pull_request(pull_request_latest) |
|
464 | member_reviewer = h.reviewer_as_json( | |
432 | q = q.order_by(ChangesetComment.comment_id.asc()) |
|
465 | member, reasons=reasons, mandatory=mandatory, | |
433 | general_comments = q |
|
466 | user_group=review_obj.rule_user_group_data() | |
|
467 | ) | |||
434 |
|
468 | |||
435 | # pick comments we want to render at current version |
|
469 | current_review_status = status[0][1].status if status else ChangesetStatus.STATUS_NOT_REVIEWED | |
436 | c.comment_versions = comments_model.aggregate_comments( |
|
470 | member_reviewer['review_status'] = current_review_status | |
437 | general_comments, versions, c.at_version_num) |
|
471 | member_reviewer['review_status_label'] = h.commit_status_lbl(current_review_status) | |
438 | c.comments = c.comment_versions[c.at_version_num]['until'] |
|
472 | member_reviewer['allowed_to_update'] = c.allowed_to_update | |
|
473 | c.pull_request_set_reviewers_data_json['reviewers'].append(member_reviewer) | |||
439 |
|
474 | |||
440 | # INLINE COMMENTS with versions # |
|
475 | c.pull_request_set_reviewers_data_json = json.dumps(c.pull_request_set_reviewers_data_json) | |
441 | q = comments_model._all_inline_comments_of_pull_request(pull_request_latest) |
|
476 | ||
442 | q = q.order_by(ChangesetComment.comment_id.asc()) |
|
477 | ||
443 | inline_comments = q |
|
|||
444 |
|
478 | |||
445 | c.inline_versions = comments_model.aggregate_comments( |
|
479 | ||
446 | inline_comments, versions, c.at_version_num, inline=True) |
|
480 | general_comments, inline_comments = \ | |
|
481 | self.register_comments_vars(c, pull_request_latest, versions) | |||
447 |
|
482 | |||
448 | # TODOs |
|
483 | # TODOs | |
449 | c.unresolved_comments = CommentsModel() \ |
|
484 | c.unresolved_comments = CommentsModel() \ | |
450 | .get_pull_request_unresolved_todos(pull_request) |
|
485 | .get_pull_request_unresolved_todos(pull_request_latest) | |
451 | c.resolved_comments = CommentsModel() \ |
|
486 | c.resolved_comments = CommentsModel() \ | |
452 | .get_pull_request_resolved_todos(pull_request) |
|
487 | .get_pull_request_resolved_todos(pull_request_latest) | |
453 |
|
||||
454 | # inject latest version |
|
|||
455 | latest_ver = PullRequest.get_pr_display_object( |
|
|||
456 | pull_request_latest, pull_request_latest) |
|
|||
457 |
|
||||
458 | c.versions = versions + [latest_ver] |
|
|||
459 |
|
488 | |||
460 | # if we use version, then do not show later comments |
|
489 | # if we use version, then do not show later comments | |
461 | # than current version |
|
490 | # than current version | |
@@ -522,8 +551,8 b' class RepoPullRequestsView(RepoAppView, ' | |||||
522 |
|
551 | |||
523 | # empty version means latest, so we keep this to prevent |
|
552 | # empty version means latest, so we keep this to prevent | |
524 | # double caching |
|
553 | # double caching | |
525 |
version_normalized = version or |
|
554 | version_normalized = version or PullRequest.LATEST_VER | |
526 |
from_version_normalized = from_version or |
|
555 | from_version_normalized = from_version or PullRequest.LATEST_VER | |
527 |
|
556 | |||
528 | cache_path = self.rhodecode_vcs_repo.get_create_shadow_cache_pr_path(target_repo) |
|
557 | cache_path = self.rhodecode_vcs_repo.get_create_shadow_cache_pr_path(target_repo) | |
529 | cache_file_path = diff_cache_exist( |
|
558 | cache_file_path = diff_cache_exist( | |
@@ -719,7 +748,7 b' class RepoPullRequestsView(RepoAppView, ' | |||||
719 |
|
748 | |||
720 | # current user review statuses for each version |
|
749 | # current user review statuses for each version | |
721 | c.review_versions = {} |
|
750 | c.review_versions = {} | |
722 | if self._rhodecode_user.user_id in allowed_reviewers: |
|
751 | if self._rhodecode_user.user_id in c.allowed_reviewers: | |
723 | for co in general_comments: |
|
752 | for co in general_comments: | |
724 | if co.author.user_id == self._rhodecode_user.user_id: |
|
753 | if co.author.user_id == self._rhodecode_user.user_id: | |
725 | status = co.status_change |
|
754 | status = co.status_change | |
@@ -939,6 +968,83 b' class RepoPullRequestsView(RepoAppView, ' | |||||
939 | @NotAnonymous() |
|
968 | @NotAnonymous() | |
940 | @HasRepoPermissionAnyDecorator( |
|
969 | @HasRepoPermissionAnyDecorator( | |
941 | 'repository.read', 'repository.write', 'repository.admin') |
|
970 | 'repository.read', 'repository.write', 'repository.admin') | |
|
971 | @view_config( | |||
|
972 | route_name='pullrequest_comments', request_method='POST', | |||
|
973 | renderer='string', xhr=True) | |||
|
974 | def pullrequest_comments(self): | |||
|
975 | self.load_default_context() | |||
|
976 | ||||
|
977 | pull_request = PullRequest.get_or_404( | |||
|
978 | self.request.matchdict['pull_request_id']) | |||
|
979 | pull_request_id = pull_request.pull_request_id | |||
|
980 | version = self.request.GET.get('version') | |||
|
981 | ||||
|
982 | _render = self.request.get_partial_renderer( | |||
|
983 | 'rhodecode:templates/pullrequests/pullrequest_show.mako') | |||
|
984 | c = _render.get_call_context() | |||
|
985 | ||||
|
986 | (pull_request_latest, | |||
|
987 | pull_request_at_ver, | |||
|
988 | pull_request_display_obj, | |||
|
989 | at_version) = PullRequestModel().get_pr_version( | |||
|
990 | pull_request_id, version=version) | |||
|
991 | versions = pull_request_display_obj.versions() | |||
|
992 | latest_ver = PullRequest.get_pr_display_object(pull_request_latest, pull_request_latest) | |||
|
993 | c.versions = versions + [latest_ver] | |||
|
994 | ||||
|
995 | c.at_version = at_version | |||
|
996 | c.at_version_num = (at_version | |||
|
997 | if at_version and at_version != PullRequest.LATEST_VER | |||
|
998 | else None) | |||
|
999 | ||||
|
1000 | self.register_comments_vars(c, pull_request_latest, versions) | |||
|
1001 | all_comments = c.inline_comments_flat + c.comments | |||
|
1002 | return _render('comments_table', all_comments, len(all_comments)) | |||
|
1003 | ||||
|
1004 | @LoginRequired() | |||
|
1005 | @NotAnonymous() | |||
|
1006 | @HasRepoPermissionAnyDecorator( | |||
|
1007 | 'repository.read', 'repository.write', 'repository.admin') | |||
|
1008 | @view_config( | |||
|
1009 | route_name='pullrequest_todos', request_method='POST', | |||
|
1010 | renderer='string', xhr=True) | |||
|
1011 | def pullrequest_todos(self): | |||
|
1012 | self.load_default_context() | |||
|
1013 | ||||
|
1014 | pull_request = PullRequest.get_or_404( | |||
|
1015 | self.request.matchdict['pull_request_id']) | |||
|
1016 | pull_request_id = pull_request.pull_request_id | |||
|
1017 | version = self.request.GET.get('version') | |||
|
1018 | ||||
|
1019 | _render = self.request.get_partial_renderer( | |||
|
1020 | 'rhodecode:templates/pullrequests/pullrequest_show.mako') | |||
|
1021 | c = _render.get_call_context() | |||
|
1022 | (pull_request_latest, | |||
|
1023 | pull_request_at_ver, | |||
|
1024 | pull_request_display_obj, | |||
|
1025 | at_version) = PullRequestModel().get_pr_version( | |||
|
1026 | pull_request_id, version=version) | |||
|
1027 | versions = pull_request_display_obj.versions() | |||
|
1028 | latest_ver = PullRequest.get_pr_display_object(pull_request_latest, pull_request_latest) | |||
|
1029 | c.versions = versions + [latest_ver] | |||
|
1030 | ||||
|
1031 | c.at_version = at_version | |||
|
1032 | c.at_version_num = (at_version | |||
|
1033 | if at_version and at_version != PullRequest.LATEST_VER | |||
|
1034 | else None) | |||
|
1035 | ||||
|
1036 | c.unresolved_comments = CommentsModel() \ | |||
|
1037 | .get_pull_request_unresolved_todos(pull_request) | |||
|
1038 | c.resolved_comments = CommentsModel() \ | |||
|
1039 | .get_pull_request_resolved_todos(pull_request) | |||
|
1040 | ||||
|
1041 | all_comments = c.unresolved_comments + c.resolved_comments | |||
|
1042 | return _render('comments_table', all_comments, len(c.unresolved_comments), todo_comments=True) | |||
|
1043 | ||||
|
1044 | @LoginRequired() | |||
|
1045 | @NotAnonymous() | |||
|
1046 | @HasRepoPermissionAnyDecorator( | |||
|
1047 | 'repository.read', 'repository.write', 'repository.admin') | |||
942 | @CSRFRequired() |
|
1048 | @CSRFRequired() | |
943 | @view_config( |
|
1049 | @view_config( | |
944 | route_name='pullrequest_create', request_method='POST', |
|
1050 | route_name='pullrequest_create', request_method='POST', | |
@@ -1100,7 +1206,7 b' class RepoPullRequestsView(RepoAppView, ' | |||||
1100 | self.request.matchdict['pull_request_id']) |
|
1206 | self.request.matchdict['pull_request_id']) | |
1101 | _ = self.request.translate |
|
1207 | _ = self.request.translate | |
1102 |
|
1208 | |||
1103 | self.load_default_context() |
|
1209 | c = self.load_default_context() | |
1104 | redirect_url = None |
|
1210 | redirect_url = None | |
1105 |
|
1211 | |||
1106 | if pull_request.is_closed(): |
|
1212 | if pull_request.is_closed(): | |
@@ -1111,6 +1217,8 b' class RepoPullRequestsView(RepoAppView, ' | |||||
1111 | 'redirect_url': redirect_url} |
|
1217 | 'redirect_url': redirect_url} | |
1112 |
|
1218 | |||
1113 | is_state_changing = pull_request.is_state_changing() |
|
1219 | is_state_changing = pull_request.is_state_changing() | |
|
1220 | c.pr_broadcast_channel = '/repo${}$/pr/{}'.format( | |||
|
1221 | pull_request.target_repo.repo_name, pull_request.pull_request_id) | |||
1114 |
|
1222 | |||
1115 | # only owner or admin can update it |
|
1223 | # only owner or admin can update it | |
1116 | allowed_to_update = PullRequestModel().check_user_update( |
|
1224 | allowed_to_update = PullRequestModel().check_user_update( | |
@@ -1134,7 +1242,7 b' class RepoPullRequestsView(RepoAppView, ' | |||||
1134 | return {'response': True, |
|
1242 | return {'response': True, | |
1135 | 'redirect_url': redirect_url} |
|
1243 | 'redirect_url': redirect_url} | |
1136 |
|
1244 | |||
1137 | self._update_commits(pull_request) |
|
1245 | self._update_commits(c, pull_request) | |
1138 | if force_refresh: |
|
1246 | if force_refresh: | |
1139 | redirect_url = h.route_path( |
|
1247 | redirect_url = h.route_path( | |
1140 | 'pullrequest_show', repo_name=self.db_repo_name, |
|
1248 | 'pullrequest_show', repo_name=self.db_repo_name, | |
@@ -1170,7 +1278,7 b' class RepoPullRequestsView(RepoAppView, ' | |||||
1170 | h.flash(msg, category='success') |
|
1278 | h.flash(msg, category='success') | |
1171 | return |
|
1279 | return | |
1172 |
|
1280 | |||
1173 | def _update_commits(self, pull_request): |
|
1281 | def _update_commits(self, c, pull_request): | |
1174 | _ = self.request.translate |
|
1282 | _ = self.request.translate | |
1175 |
|
1283 | |||
1176 | with pull_request.set_state(PullRequest.STATE_UPDATING): |
|
1284 | with pull_request.set_state(PullRequest.STATE_UPDATING): | |
@@ -1198,13 +1306,18 b' class RepoPullRequestsView(RepoAppView, ' | |||||
1198 | change_source=changed) |
|
1306 | change_source=changed) | |
1199 | h.flash(msg, category='success') |
|
1307 | h.flash(msg, category='success') | |
1200 |
|
1308 | |||
1201 | channel = '/repo${}$/pr/{}'.format( |
|
|||
1202 | pull_request.target_repo.repo_name, pull_request.pull_request_id) |
|
|||
1203 | message = msg + ( |
|
1309 | message = msg + ( | |
1204 | ' - <a onclick="window.location.reload()">' |
|
1310 | ' - <a onclick="window.location.reload()">' | |
1205 | '<strong>{}</strong></a>'.format(_('Reload page'))) |
|
1311 | '<strong>{}</strong></a>'.format(_('Reload page'))) | |
|
1312 | ||||
|
1313 | message_obj = { | |||
|
1314 | 'message': message, | |||
|
1315 | 'level': 'success', | |||
|
1316 | 'topic': '/notifications' | |||
|
1317 | } | |||
|
1318 | ||||
1206 | channelstream.post_message( |
|
1319 | channelstream.post_message( | |
1207 | channel, message, self._rhodecode_user.username, |
|
1320 | c.pr_broadcast_channel, message_obj, self._rhodecode_user.username, | |
1208 | registry=self.request.registry) |
|
1321 | registry=self.request.registry) | |
1209 | else: |
|
1322 | else: | |
1210 | msg = PullRequestModel.UPDATE_STATUS_MESSAGES[resp.reason] |
|
1323 | msg = PullRequestModel.UPDATE_STATUS_MESSAGES[resp.reason] | |
@@ -1474,6 +1587,7 b' class RepoPullRequestsView(RepoAppView, ' | |||||
1474 | } |
|
1587 | } | |
1475 | if comment: |
|
1588 | if comment: | |
1476 | c.co = comment |
|
1589 | c.co = comment | |
|
1590 | c.at_version_num = None | |||
1477 | rendered_comment = render( |
|
1591 | rendered_comment = render( | |
1478 | 'rhodecode:templates/changeset/changeset_comment_block.mako', |
|
1592 | 'rhodecode:templates/changeset/changeset_comment_block.mako', | |
1479 | self._get_template_context(c), self.request) |
|
1593 | self._get_template_context(c), self.request) |
@@ -810,8 +810,7 b' import tzlocal' | |||||
810 | local_timezone = tzlocal.get_localzone() |
|
810 | local_timezone = tzlocal.get_localzone() | |
811 |
|
811 | |||
812 |
|
812 | |||
813 |
def |
|
813 | def get_timezone(datetime_iso, time_is_local=False): | |
814 | title = value or format_date(datetime_iso) |
|
|||
815 | tzinfo = '+00:00' |
|
814 | tzinfo = '+00:00' | |
816 |
|
815 | |||
817 | # detect if we have a timezone info, otherwise, add it |
|
816 | # detect if we have a timezone info, otherwise, add it | |
@@ -822,6 +821,12 b' def age_component(datetime_iso, value=No' | |||||
822 | timezone = force_timezone or local_timezone |
|
821 | timezone = force_timezone or local_timezone | |
823 | offset = timezone.localize(datetime_iso).strftime('%z') |
|
822 | offset = timezone.localize(datetime_iso).strftime('%z') | |
824 | tzinfo = '{}:{}'.format(offset[:-2], offset[-2:]) |
|
823 | tzinfo = '{}:{}'.format(offset[:-2], offset[-2:]) | |
|
824 | return tzinfo | |||
|
825 | ||||
|
826 | ||||
|
827 | def age_component(datetime_iso, value=None, time_is_local=False, tooltip=True): | |||
|
828 | title = value or format_date(datetime_iso) | |||
|
829 | tzinfo = get_timezone(datetime_iso, time_is_local=time_is_local) | |||
825 |
|
830 | |||
826 | return literal( |
|
831 | return literal( | |
827 | '<time class="timeago {cls}" title="{tt_title}" datetime="{dt}{tzinfo}">{title}</time>'.format( |
|
832 | '<time class="timeago {cls}" title="{tt_title}" datetime="{dt}{tzinfo}">{title}</time>'.format( | |
@@ -1650,17 +1655,18 b' def get_active_pattern_entries(repo_name' | |||||
1650 |
|
1655 | |||
1651 | pr_pattern_re = re.compile(r'(?:(?:^!)|(?: !))(\d+)') |
|
1656 | pr_pattern_re = re.compile(r'(?:(?:^!)|(?: !))(\d+)') | |
1652 |
|
1657 | |||
|
1658 | allowed_link_formats = [ | |||
|
1659 | 'html', 'rst', 'markdown', 'html+hovercard', 'rst+hovercard', 'markdown+hovercard'] | |||
|
1660 | ||||
1653 |
|
1661 | |||
1654 | def process_patterns(text_string, repo_name, link_format='html', active_entries=None): |
|
1662 | def process_patterns(text_string, repo_name, link_format='html', active_entries=None): | |
1655 |
|
1663 | |||
1656 | allowed_formats = ['html', 'rst', 'markdown', |
|
1664 | if link_format not in allowed_link_formats: | |
1657 | 'html+hovercard', 'rst+hovercard', 'markdown+hovercard'] |
|
|||
1658 | if link_format not in allowed_formats: |
|
|||
1659 | raise ValueError('Link format can be only one of:{} got {}'.format( |
|
1665 | raise ValueError('Link format can be only one of:{} got {}'.format( | |
1660 | allowed_formats, link_format)) |
|
1666 | allowed_link_formats, link_format)) | |
1661 |
|
1667 | |||
1662 | if active_entries is None: |
|
1668 | if active_entries is None: | |
1663 | log.debug('Fetch active patterns for repo: %s', repo_name) |
|
1669 | log.debug('Fetch active issue tracker patterns for repo: %s', repo_name) | |
1664 | active_entries = get_active_pattern_entries(repo_name) |
|
1670 | active_entries = get_active_pattern_entries(repo_name) | |
1665 |
|
1671 | |||
1666 | issues_data = [] |
|
1672 | issues_data = [] | |
@@ -1718,7 +1724,8 b' def process_patterns(text_string, repo_n' | |||||
1718 | return new_text, issues_data |
|
1724 | return new_text, issues_data | |
1719 |
|
1725 | |||
1720 |
|
1726 | |||
1721 |
def urlify_commit_message(commit_text, repository=None, active_pattern_entries=None |
|
1727 | def urlify_commit_message(commit_text, repository=None, active_pattern_entries=None, | |
|
1728 | issues_container=None): | |||
1722 | """ |
|
1729 | """ | |
1723 | Parses given text message and makes proper links. |
|
1730 | Parses given text message and makes proper links. | |
1724 | issues are linked to given issue-server, and rest is a commit link |
|
1731 | issues are linked to given issue-server, and rest is a commit link | |
@@ -1741,6 +1748,9 b' def urlify_commit_message(commit_text, r' | |||||
1741 | new_text, issues = process_patterns(new_text, repository or '', |
|
1748 | new_text, issues = process_patterns(new_text, repository or '', | |
1742 | active_entries=active_pattern_entries) |
|
1749 | active_entries=active_pattern_entries) | |
1743 |
|
1750 | |||
|
1751 | if issues_container is not None: | |||
|
1752 | issues_container.extend(issues) | |||
|
1753 | ||||
1744 | return literal(new_text) |
|
1754 | return literal(new_text) | |
1745 |
|
1755 | |||
1746 |
|
1756 | |||
@@ -1781,7 +1791,7 b' def renderer_from_filename(filename, exc' | |||||
1781 |
|
1791 | |||
1782 |
|
1792 | |||
1783 | def render(source, renderer='rst', mentions=False, relative_urls=None, |
|
1793 | def render(source, renderer='rst', mentions=False, relative_urls=None, | |
1784 | repo_name=None, active_pattern_entries=None): |
|
1794 | repo_name=None, active_pattern_entries=None, issues_container=None): | |
1785 |
|
1795 | |||
1786 | def maybe_convert_relative_links(html_source): |
|
1796 | def maybe_convert_relative_links(html_source): | |
1787 | if relative_urls: |
|
1797 | if relative_urls: | |
@@ -1798,6 +1808,8 b" def render(source, renderer='rst', menti" | |||||
1798 | source, issues = process_patterns( |
|
1808 | source, issues = process_patterns( | |
1799 | source, repo_name, link_format='rst', |
|
1809 | source, repo_name, link_format='rst', | |
1800 | active_entries=active_pattern_entries) |
|
1810 | active_entries=active_pattern_entries) | |
|
1811 | if issues_container is not None: | |||
|
1812 | issues_container.extend(issues) | |||
1801 |
|
1813 | |||
1802 | return literal( |
|
1814 | return literal( | |
1803 | '<div class="rst-block">%s</div>' % |
|
1815 | '<div class="rst-block">%s</div>' % | |
@@ -1810,6 +1822,8 b" def render(source, renderer='rst', menti" | |||||
1810 | source, issues = process_patterns( |
|
1822 | source, issues = process_patterns( | |
1811 | source, repo_name, link_format='markdown', |
|
1823 | source, repo_name, link_format='markdown', | |
1812 | active_entries=active_pattern_entries) |
|
1824 | active_entries=active_pattern_entries) | |
|
1825 | if issues_container is not None: | |||
|
1826 | issues_container.extend(issues) | |||
1813 |
|
1827 | |||
1814 | return literal( |
|
1828 | return literal( | |
1815 | '<div class="markdown-block">%s</div>' % |
|
1829 | '<div class="markdown-block">%s</div>' % |
@@ -91,8 +91,7 b' class CommentsModel(BaseModel):' | |||||
91 | # group by versions, and count until, and display objects |
|
91 | # group by versions, and count until, and display objects | |
92 |
|
92 | |||
93 | comment_groups = collections.defaultdict(list) |
|
93 | comment_groups = collections.defaultdict(list) | |
94 | [comment_groups[ |
|
94 | [comment_groups[_co.pull_request_version_id].append(_co) for _co in comments] | |
95 | _co.pull_request_version_id].append(_co) for _co in comments] |
|
|||
96 |
|
95 | |||
97 | def yield_comments(pos): |
|
96 | def yield_comments(pos): | |
98 | for co in comment_groups[pos]: |
|
97 | for co in comment_groups[pos]: | |
@@ -456,37 +455,53 b' class CommentsModel(BaseModel):' | |||||
456 | else: |
|
455 | else: | |
457 | action = 'repo.commit.comment.create' |
|
456 | action = 'repo.commit.comment.create' | |
458 |
|
457 | |||
|
458 | comment_id = comment.comment_id | |||
459 | comment_data = comment.get_api_data() |
|
459 | comment_data = comment.get_api_data() | |
|
460 | ||||
460 | self._log_audit_action( |
|
461 | self._log_audit_action( | |
461 | action, {'data': comment_data}, auth_user, comment) |
|
462 | action, {'data': comment_data}, auth_user, comment) | |
462 |
|
463 | |||
463 | msg_url = '' |
|
|||
464 | channel = None |
|
464 | channel = None | |
465 | if commit_obj: |
|
465 | if commit_obj: | |
466 | msg_url = commit_comment_url |
|
|||
467 | repo_name = repo.repo_name |
|
466 | repo_name = repo.repo_name | |
468 | channel = u'/repo${}$/commit/{}'.format( |
|
467 | channel = u'/repo${}$/commit/{}'.format( | |
469 | repo_name, |
|
468 | repo_name, | |
470 | commit_obj.raw_id |
|
469 | commit_obj.raw_id | |
471 | ) |
|
470 | ) | |
472 | elif pull_request_obj: |
|
471 | elif pull_request_obj: | |
473 | msg_url = pr_comment_url |
|
|||
474 | repo_name = pr_target_repo.repo_name |
|
472 | repo_name = pr_target_repo.repo_name | |
475 | channel = u'/repo${}$/pr/{}'.format( |
|
473 | channel = u'/repo${}$/pr/{}'.format( | |
476 | repo_name, |
|
474 | repo_name, | |
477 | pull_request_id |
|
475 | pull_request_obj.pull_request_id | |
478 | ) |
|
476 | ) | |
479 |
|
477 | |||
480 | message = '<strong>{}</strong> {} - ' \ |
|
478 | if channel: | |
481 | '<a onclick="window.location=\'{}\';' \ |
|
479 | username = user.username | |
482 | 'window.location.reload()">' \ |
|
480 | message = '<strong>{}</strong> {} #{}, {}' | |
483 | '<strong>{}</strong></a>' |
|
|||
484 | message = message.format( |
|
481 | message = message.format( | |
485 | user.username, _('made a comment'), msg_url, |
|
482 | username, | |
486 | _('Show it now')) |
|
483 | _('posted a new comment'), | |
|
484 | comment_id, | |||
|
485 | _('Refresh the page to see new comments.')) | |||
|
486 | ||||
|
487 | message_obj = { | |||
|
488 | 'message': message, | |||
|
489 | 'level': 'success', | |||
|
490 | 'topic': '/notifications' | |||
|
491 | } | |||
487 |
|
492 | |||
488 | channelstream.post_message( |
|
493 | channelstream.post_message( | |
489 | channel, message, user.username, |
|
494 | channel, message_obj, user.username, | |
|
495 | registry=get_current_registry()) | |||
|
496 | ||||
|
497 | message_obj = { | |||
|
498 | 'message': None, | |||
|
499 | 'user': username, | |||
|
500 | 'comment_id': comment_id, | |||
|
501 | 'topic': '/comment' | |||
|
502 | } | |||
|
503 | channelstream.post_message( | |||
|
504 | channel, message_obj, user.username, | |||
490 | registry=get_current_registry()) |
|
505 | registry=get_current_registry()) | |
491 |
|
506 | |||
492 | return comment |
|
507 | return comment | |
@@ -643,14 +658,14 b' class CommentsModel(BaseModel):' | |||||
643 |
|
658 | |||
644 | def get_inline_comments_as_list(self, inline_comments, skip_outdated=True, |
|
659 | def get_inline_comments_as_list(self, inline_comments, skip_outdated=True, | |
645 | version=None): |
|
660 | version=None): | |
646 |
inline_c |
|
661 | inline_comms = [] | |
647 | for fname, per_line_comments in inline_comments.iteritems(): |
|
662 | for fname, per_line_comments in inline_comments.iteritems(): | |
648 | for lno, comments in per_line_comments.iteritems(): |
|
663 | for lno, comments in per_line_comments.iteritems(): | |
649 | for comm in comments: |
|
664 | for comm in comments: | |
650 | if not comm.outdated_at_version(version) and skip_outdated: |
|
665 | if not comm.outdated_at_version(version) and skip_outdated: | |
651 |
inline_c |
|
666 | inline_comms.append(comm) | |
652 |
|
667 | |||
653 |
return inline_c |
|
668 | return inline_comms | |
654 |
|
669 | |||
655 | def get_outdated_comments(self, repo_id, pull_request): |
|
670 | def get_outdated_comments(self, repo_id, pull_request): | |
656 | # TODO: johbo: Remove `repo_id`, it is not needed to find the comments |
|
671 | # TODO: johbo: Remove `repo_id`, it is not needed to find the comments |
@@ -3821,16 +3821,35 b' class ChangesetComment(Base, BaseModel):' | |||||
3821 | """ |
|
3821 | """ | |
3822 | Checks if comment is outdated for given pull request version |
|
3822 | Checks if comment is outdated for given pull request version | |
3823 | """ |
|
3823 | """ | |
3824 | return self.outdated and self.pull_request_version_id != version |
|
3824 | def version_check(): | |
|
3825 | return self.pull_request_version_id and self.pull_request_version_id != version | |||
|
3826 | ||||
|
3827 | if self.is_inline: | |||
|
3828 | return self.outdated and version_check() | |||
|
3829 | else: | |||
|
3830 | # general comments don't have .outdated set, also latest don't have a version | |||
|
3831 | return version_check() | |||
|
3832 | ||||
|
3833 | def outdated_at_version_js(self, version): | |||
|
3834 | """ | |||
|
3835 | Checks if comment is outdated for given pull request version | |||
|
3836 | """ | |||
|
3837 | return json.dumps(self.outdated_at_version(version)) | |||
3825 |
|
3838 | |||
3826 | def older_than_version(self, version): |
|
3839 | def older_than_version(self, version): | |
3827 | """ |
|
3840 | """ | |
3828 | Checks if comment is made from previous version than given |
|
3841 | Checks if comment is made from previous version than given | |
3829 | """ |
|
3842 | """ | |
3830 | if version is None: |
|
3843 | if version is None: | |
3831 |
return self.pull_request_version |
|
3844 | return self.pull_request_version != version | |
3832 |
|
3845 | |||
3833 |
return self.pull_request_version |
|
3846 | return self.pull_request_version < version | |
|
3847 | ||||
|
3848 | def older_than_version_js(self, version): | |||
|
3849 | """ | |||
|
3850 | Checks if comment is made from previous version than given | |||
|
3851 | """ | |||
|
3852 | return json.dumps(self.older_than_version(version)) | |||
3834 |
|
3853 | |||
3835 | @property |
|
3854 | @property | |
3836 | def commit_id(self): |
|
3855 | def commit_id(self): | |
@@ -4327,6 +4346,7 b' class PullRequest(Base, _PullRequestBase' | |||||
4327 | __table_args__ = ( |
|
4346 | __table_args__ = ( | |
4328 | base_table_args, |
|
4347 | base_table_args, | |
4329 | ) |
|
4348 | ) | |
|
4349 | LATEST_VER = 'latest' | |||
4330 |
|
4350 | |||
4331 | pull_request_id = Column( |
|
4351 | pull_request_id = Column( | |
4332 | 'pull_request_id', Integer(), nullable=False, primary_key=True) |
|
4352 | 'pull_request_id', Integer(), nullable=False, primary_key=True) | |
@@ -4385,6 +4405,10 b' class PullRequest(Base, _PullRequestBase' | |||||
4385 | def pull_request_version_id(self): |
|
4405 | def pull_request_version_id(self): | |
4386 | return getattr(pull_request_obj, 'pull_request_version_id', None) |
|
4406 | return getattr(pull_request_obj, 'pull_request_version_id', None) | |
4387 |
|
4407 | |||
|
4408 | @property | |||
|
4409 | def pull_request_last_version(self): | |||
|
4410 | return pull_request_obj.pull_request_last_version | |||
|
4411 | ||||
4388 | attrs = StrictAttributeDict(pull_request_obj.get_api_data(with_merge_state=False)) |
|
4412 | attrs = StrictAttributeDict(pull_request_obj.get_api_data(with_merge_state=False)) | |
4389 |
|
4413 | |||
4390 | attrs.author = StrictAttributeDict( |
|
4414 | attrs.author = StrictAttributeDict( | |
@@ -4449,6 +4473,10 b' class PullRequest(Base, _PullRequestBase' | |||||
4449 | """ |
|
4473 | """ | |
4450 | return self.versions.count() + 1 |
|
4474 | return self.versions.count() + 1 | |
4451 |
|
4475 | |||
|
4476 | @property | |||
|
4477 | def pull_request_last_version(self): | |||
|
4478 | return self.versions_count | |||
|
4479 | ||||
4452 |
|
4480 | |||
4453 | class PullRequestVersion(Base, _PullRequestBase): |
|
4481 | class PullRequestVersion(Base, _PullRequestBase): | |
4454 | __tablename__ = 'pull_request_versions' |
|
4482 | __tablename__ = 'pull_request_versions' |
@@ -240,14 +240,14 b' div.markdown-block ol {' | |||||
240 | div.markdown-block ul.checkbox li, |
|
240 | div.markdown-block ul.checkbox li, | |
241 | div.markdown-block ol.checkbox li { |
|
241 | div.markdown-block ol.checkbox li { | |
242 | list-style: none !important; |
|
242 | list-style: none !important; | |
243 |
margin: |
|
243 | margin: 0px !important; | |
244 | padding: 0 !important; |
|
244 | padding: 0 !important; | |
245 | } |
|
245 | } | |
246 |
|
246 | |||
247 | div.markdown-block ul li, |
|
247 | div.markdown-block ul li, | |
248 | div.markdown-block ol li { |
|
248 | div.markdown-block ol li { | |
249 | list-style: disc !important; |
|
249 | list-style: disc !important; | |
250 |
margin: |
|
250 | margin: 0px !important; | |
251 | padding: 0 !important; |
|
251 | padding: 0 !important; | |
252 | } |
|
252 | } | |
253 |
|
253 |
@@ -1510,18 +1510,14 b' table.integrations {' | |||||
1510 | min-height: 55px; |
|
1510 | min-height: 55px; | |
1511 | } |
|
1511 | } | |
1512 |
|
1512 | |||
1513 | .reviewers_member { |
|
|||
1514 | width: 100%; |
|
|||
1515 | overflow: auto; |
|
|||
1516 | } |
|
|||
1517 | .reviewer_reason { |
|
1513 | .reviewer_reason { | |
1518 | padding-left: 20px; |
|
1514 | padding-left: 20px; | |
1519 | line-height: 1.5em; |
|
1515 | line-height: 1.5em; | |
1520 | } |
|
1516 | } | |
1521 | .reviewer_status { |
|
1517 | .reviewer_status { | |
1522 | display: inline-block; |
|
1518 | display: inline-block; | |
1523 |
width: 2 |
|
1519 | width: 20px; | |
1524 |
min-width: 2 |
|
1520 | min-width: 20px; | |
1525 | height: 1.2em; |
|
1521 | height: 1.2em; | |
1526 | line-height: 1em; |
|
1522 | line-height: 1em; | |
1527 | } |
|
1523 | } | |
@@ -1544,23 +1540,17 b' table.integrations {' | |||||
1544 | } |
|
1540 | } | |
1545 |
|
1541 | |||
1546 | .reviewer_member_mandatory { |
|
1542 | .reviewer_member_mandatory { | |
1547 | position: absolute; |
|
|||
1548 | left: 15px; |
|
|||
1549 | top: 8px; |
|
|||
1550 | width: 16px; |
|
1543 | width: 16px; | |
1551 | font-size: 11px; |
|
1544 | font-size: 11px; | |
1552 | margin: 0; |
|
1545 | margin: 0; | |
1553 | padding: 0; |
|
1546 | padding: 0; | |
1554 | color: black; |
|
1547 | color: black; | |
|
1548 | opacity: 0.4; | |||
1555 | } |
|
1549 | } | |
1556 |
|
1550 | |||
1557 | .reviewer_member_mandatory_remove, |
|
1551 | .reviewer_member_mandatory_remove, | |
1558 | .reviewer_member_remove { |
|
1552 | .reviewer_member_remove { | |
1559 | position: absolute; |
|
|||
1560 | right: 0; |
|
|||
1561 | top: 0; |
|
|||
1562 | width: 16px; |
|
1553 | width: 16px; | |
1563 | margin-bottom: 10px; |
|
|||
1564 | padding: 0; |
|
1554 | padding: 0; | |
1565 | color: black; |
|
1555 | color: black; | |
1566 | } |
|
1556 | } | |
@@ -1617,7 +1607,8 b' table.integrations {' | |||||
1617 | .td-todo-number { |
|
1607 | .td-todo-number { | |
1618 | text-align: left; |
|
1608 | text-align: left; | |
1619 | white-space: nowrap; |
|
1609 | white-space: nowrap; | |
1620 |
width: 1 |
|
1610 | width: 1%; | |
|
1611 | padding-right: 2px; | |||
1621 | } |
|
1612 | } | |
1622 |
|
1613 | |||
1623 | .td-todo-gravatar { |
|
1614 | .td-todo-gravatar { | |
@@ -1641,10 +1632,13 b' table.integrations {' | |||||
1641 | text-overflow: ellipsis; |
|
1632 | text-overflow: ellipsis; | |
1642 | } |
|
1633 | } | |
1643 |
|
1634 | |||
|
1635 | table.group_members { | |||
|
1636 | width: 100% | |||
|
1637 | } | |||
|
1638 | ||||
1644 | .group_members { |
|
1639 | .group_members { | |
1645 | margin-top: 0; |
|
1640 | margin-top: 0; | |
1646 | padding: 0; |
|
1641 | padding: 0; | |
1647 | list-style: outside none none; |
|
|||
1648 |
|
1642 | |||
1649 | img { |
|
1643 | img { | |
1650 | height: @gravatar-size; |
|
1644 | height: @gravatar-size; |
@@ -246,6 +246,8 b' function registerRCRoutes() {' | |||||
246 | pyroutes.register('pullrequest_comment_create', '/%(repo_name)s/pull-request/%(pull_request_id)s/comment', ['repo_name', 'pull_request_id']); |
|
246 | pyroutes.register('pullrequest_comment_create', '/%(repo_name)s/pull-request/%(pull_request_id)s/comment', ['repo_name', 'pull_request_id']); | |
247 | pyroutes.register('pullrequest_comment_edit', '/%(repo_name)s/pull-request/%(pull_request_id)s/comment/%(comment_id)s/edit', ['repo_name', 'pull_request_id', 'comment_id']); |
|
247 | pyroutes.register('pullrequest_comment_edit', '/%(repo_name)s/pull-request/%(pull_request_id)s/comment/%(comment_id)s/edit', ['repo_name', 'pull_request_id', 'comment_id']); | |
248 | pyroutes.register('pullrequest_comment_delete', '/%(repo_name)s/pull-request/%(pull_request_id)s/comment/%(comment_id)s/delete', ['repo_name', 'pull_request_id', 'comment_id']); |
|
248 | pyroutes.register('pullrequest_comment_delete', '/%(repo_name)s/pull-request/%(pull_request_id)s/comment/%(comment_id)s/delete', ['repo_name', 'pull_request_id', 'comment_id']); | |
|
249 | pyroutes.register('pullrequest_comments', '/%(repo_name)s/pull-request/%(pull_request_id)s/comments', ['repo_name', 'pull_request_id']); | |||
|
250 | pyroutes.register('pullrequest_todos', '/%(repo_name)s/pull-request/%(pull_request_id)s/todos', ['repo_name', 'pull_request_id']); | |||
249 | pyroutes.register('edit_repo', '/%(repo_name)s/settings', ['repo_name']); |
|
251 | pyroutes.register('edit_repo', '/%(repo_name)s/settings', ['repo_name']); | |
250 | pyroutes.register('edit_repo_advanced', '/%(repo_name)s/settings/advanced', ['repo_name']); |
|
252 | pyroutes.register('edit_repo_advanced', '/%(repo_name)s/settings/advanced', ['repo_name']); | |
251 | pyroutes.register('edit_repo_advanced_archive', '/%(repo_name)s/settings/advanced/archive', ['repo_name']); |
|
253 | pyroutes.register('edit_repo_advanced_archive', '/%(repo_name)s/settings/advanced/archive', ['repo_name']); |
@@ -28,9 +28,12 b' export class RhodecodeApp extends Polyme' | |||||
28 | super.connectedCallback(); |
|
28 | super.connectedCallback(); | |
29 | ccLog.debug('rhodeCodeApp created'); |
|
29 | ccLog.debug('rhodeCodeApp created'); | |
30 | $.Topic('/notifications').subscribe(this.handleNotifications.bind(this)); |
|
30 | $.Topic('/notifications').subscribe(this.handleNotifications.bind(this)); | |
|
31 | $.Topic('/comment').subscribe(this.handleComment.bind(this)); | |||
31 | $.Topic('/favicon/update').subscribe(this.faviconUpdate.bind(this)); |
|
32 | $.Topic('/favicon/update').subscribe(this.faviconUpdate.bind(this)); | |
32 | $.Topic('/connection_controller/subscribe').subscribe( |
|
33 | $.Topic('/connection_controller/subscribe').subscribe( | |
33 |
this.subscribeToChannelTopic.bind(this) |
|
34 | this.subscribeToChannelTopic.bind(this) | |
|
35 | ); | |||
|
36 | ||||
34 | // this event can be used to coordinate plugins to do their |
|
37 | // this event can be used to coordinate plugins to do their | |
35 | // initialization before channelstream is kicked off |
|
38 | // initialization before channelstream is kicked off | |
36 | $.Topic('/__MAIN_APP__').publish({}); |
|
39 | $.Topic('/__MAIN_APP__').publish({}); | |
@@ -71,6 +74,14 b' export class RhodecodeApp extends Polyme' | |||||
71 |
|
74 | |||
72 | } |
|
75 | } | |
73 |
|
76 | |||
|
77 | handleComment(data) { | |||
|
78 | if (data.message.comment_id) { | |||
|
79 | if (window.refreshAllComments !== undefined) { | |||
|
80 | refreshAllComments() | |||
|
81 | } | |||
|
82 | } | |||
|
83 | } | |||
|
84 | ||||
74 | faviconUpdate(data) { |
|
85 | faviconUpdate(data) { | |
75 | this.shadowRoot.querySelector('rhodecode-favicon').counter = data.count; |
|
86 | this.shadowRoot.querySelector('rhodecode-favicon').counter = data.count; | |
76 | } |
|
87 | } | |
@@ -95,6 +106,7 b' export class RhodecodeApp extends Polyme' | |||||
95 | } |
|
106 | } | |
96 | // append any additional channels registered in other plugins |
|
107 | // append any additional channels registered in other plugins | |
97 | $.Topic('/connection_controller/subscribe').processPrepared(); |
|
108 | $.Topic('/connection_controller/subscribe').processPrepared(); | |
|
109 | ||||
98 | channelstreamConnection.connect(); |
|
110 | channelstreamConnection.connect(); | |
99 | } |
|
111 | } | |
100 | } |
|
112 | } | |
@@ -157,8 +169,7 b' export class RhodecodeApp extends Polyme' | |||||
157 |
|
169 | |||
158 | handleConnected(event) { |
|
170 | handleConnected(event) { | |
159 | var channelstreamConnection = this.getChannelStreamConnection(); |
|
171 | var channelstreamConnection = this.getChannelStreamConnection(); | |
160 | channelstreamConnection.set('channelsState', |
|
172 | channelstreamConnection.set('channelsState', event.detail.channels_info); | |
161 | event.detail.channels_info); |
|
|||
162 | channelstreamConnection.set('userState', event.detail.state); |
|
173 | channelstreamConnection.set('userState', event.detail.state); | |
163 | channelstreamConnection.set('channels', event.detail.channels); |
|
174 | channelstreamConnection.set('channels', event.detail.channels); | |
164 | this.propagageChannelsState(); |
|
175 | this.propagageChannelsState(); |
@@ -677,7 +677,9 b' var feedLifetimeOptions = function(query' | |||||
677 | query.callback(data); |
|
677 | query.callback(data); | |
678 | }; |
|
678 | }; | |
679 |
|
679 | |||
680 |
|
680 | /* | ||
|
681 | * Retrievew via templateContext.session_attrs.key | |||
|
682 | * */ | |||
681 | var storeUserSessionAttr = function (key, val) { |
|
683 | var storeUserSessionAttr = function (key, val) { | |
682 |
|
684 | |||
683 | var postData = { |
|
685 | var postData = { |
@@ -670,8 +670,20 b' var CommentsController = function() {' | |||||
670 |
|
670 | |||
671 | var success = function(response) { |
|
671 | var success = function(response) { | |
672 | $comment.remove(); |
|
672 | $comment.remove(); | |
|
673 | ||||
|
674 | if (window.updateSticky !== undefined) { | |||
|
675 | // potentially our comments change the active window size, so we | |||
|
676 | // notify sticky elements | |||
|
677 | updateSticky() | |||
|
678 | } | |||
|
679 | ||||
|
680 | if (window.refreshAllComments !== undefined) { | |||
|
681 | // if we have this handler, run it, and refresh all comments boxes | |||
|
682 | refreshAllComments() | |||
|
683 | } | |||
673 | return false; |
|
684 | return false; | |
674 | }; |
|
685 | }; | |
|
686 | ||||
675 | var failure = function(jqXHR, textStatus, errorThrown) { |
|
687 | var failure = function(jqXHR, textStatus, errorThrown) { | |
676 | var prefix = "Error while deleting this comment.\n" |
|
688 | var prefix = "Error while deleting this comment.\n" | |
677 | var message = formatErrorMessage(jqXHR, textStatus, errorThrown, prefix); |
|
689 | var message = formatErrorMessage(jqXHR, textStatus, errorThrown, prefix); | |
@@ -682,6 +694,9 b' var CommentsController = function() {' | |||||
682 | return false; |
|
694 | return false; | |
683 | }; |
|
695 | }; | |
684 | ajaxPOST(url, postData, success, failure); |
|
696 | ajaxPOST(url, postData, success, failure); | |
|
697 | ||||
|
698 | ||||
|
699 | ||||
685 | } |
|
700 | } | |
686 |
|
701 | |||
687 | this.deleteComment = function(node) { |
|
702 | this.deleteComment = function(node) { | |
@@ -727,6 +742,15 b' var CommentsController = function() {' | |||||
727 | $filediff.find('.hide-line-comments').removeClass('hide-line-comments'); |
|
742 | $filediff.find('.hide-line-comments').removeClass('hide-line-comments'); | |
728 | $filediff.toggleClass('hide-comments'); |
|
743 | $filediff.toggleClass('hide-comments'); | |
729 | } |
|
744 | } | |
|
745 | ||||
|
746 | // since we change the height of the diff container that has anchor points for upper | |||
|
747 | // sticky header, we need to tell it to re-calculate those | |||
|
748 | if (window.updateSticky !== undefined) { | |||
|
749 | // potentially our comments change the active window size, so we | |||
|
750 | // notify sticky elements | |||
|
751 | updateSticky() | |||
|
752 | } | |||
|
753 | ||||
730 | return false; |
|
754 | return false; | |
731 | }; |
|
755 | }; | |
732 |
|
756 | |||
@@ -747,7 +771,7 b' var CommentsController = function() {' | |||||
747 | var cm = commentForm.getCmInstance(); |
|
771 | var cm = commentForm.getCmInstance(); | |
748 |
|
772 | |||
749 | if (resolvesCommentId){ |
|
773 | if (resolvesCommentId){ | |
750 |
|
|
774 | placeholderText = _gettext('Leave a resolution comment, or click resolve button to resolve TODO comment #{0}').format(resolvesCommentId); | |
751 | } |
|
775 | } | |
752 |
|
776 | |||
753 | setTimeout(function() { |
|
777 | setTimeout(function() { | |
@@ -1077,9 +1101,15 b' var CommentsController = function() {' | |||||
1077 | updateSticky() |
|
1101 | updateSticky() | |
1078 | } |
|
1102 | } | |
1079 |
|
1103 | |||
|
1104 | if (window.refreshAllComments !== undefined) { | |||
|
1105 | // if we have this handler, run it, and refresh all comments boxes | |||
|
1106 | refreshAllComments() | |||
|
1107 | } | |||
|
1108 | ||||
1080 | commentForm.setActionButtonsDisabled(false); |
|
1109 | commentForm.setActionButtonsDisabled(false); | |
1081 |
|
1110 | |||
1082 | }; |
|
1111 | }; | |
|
1112 | ||||
1083 | var submitFailCallback = function(jqXHR, textStatus, errorThrown) { |
|
1113 | var submitFailCallback = function(jqXHR, textStatus, errorThrown) { | |
1084 | var prefix = "Error while editing comment.\n" |
|
1114 | var prefix = "Error while editing comment.\n" | |
1085 | var message = formatErrorMessage(jqXHR, textStatus, errorThrown, prefix); |
|
1115 | var message = formatErrorMessage(jqXHR, textStatus, errorThrown, prefix); | |
@@ -1209,6 +1239,11 b' var CommentsController = function() {' | |||||
1209 | updateSticky() |
|
1239 | updateSticky() | |
1210 | } |
|
1240 | } | |
1211 |
|
1241 | |||
|
1242 | if (window.refreshAllComments !== undefined) { | |||
|
1243 | // if we have this handler, run it, and refresh all comments boxes | |||
|
1244 | refreshAllComments() | |||
|
1245 | } | |||
|
1246 | ||||
1212 | commentForm.setActionButtonsDisabled(false); |
|
1247 | commentForm.setActionButtonsDisabled(false); | |
1213 |
|
1248 | |||
1214 | }; |
|
1249 | }; |
@@ -98,10 +98,13 b' ReviewersController = function () {' | |||||
98 | var self = this; |
|
98 | var self = this; | |
99 | this.$reviewRulesContainer = $('#review_rules'); |
|
99 | this.$reviewRulesContainer = $('#review_rules'); | |
100 | this.$rulesList = this.$reviewRulesContainer.find('.pr-reviewer-rules'); |
|
100 | this.$rulesList = this.$reviewRulesContainer.find('.pr-reviewer-rules'); | |
|
101 | this.$userRule = $('.pr-user-rule-container'); | |||
101 | this.forbidReviewUsers = undefined; |
|
102 | this.forbidReviewUsers = undefined; | |
102 | this.$reviewMembers = $('#review_members'); |
|
103 | this.$reviewMembers = $('#review_members'); | |
103 | this.currentRequest = null; |
|
104 | this.currentRequest = null; | |
104 | this.diffData = null; |
|
105 | this.diffData = null; | |
|
106 | this.enabledRules = []; | |||
|
107 | ||||
105 | //dummy handler, we might register our own later |
|
108 | //dummy handler, we might register our own later | |
106 | this.diffDataHandler = function(data){}; |
|
109 | this.diffDataHandler = function(data){}; | |
107 |
|
110 | |||
@@ -116,14 +119,17 b' ReviewersController = function () {' | |||||
116 |
|
119 | |||
117 | this.hideReviewRules = function () { |
|
120 | this.hideReviewRules = function () { | |
118 | self.$reviewRulesContainer.hide(); |
|
121 | self.$reviewRulesContainer.hide(); | |
|
122 | $(self.$userRule.selector).hide(); | |||
119 | }; |
|
123 | }; | |
120 |
|
124 | |||
121 | this.showReviewRules = function () { |
|
125 | this.showReviewRules = function () { | |
122 | self.$reviewRulesContainer.show(); |
|
126 | self.$reviewRulesContainer.show(); | |
|
127 | $(self.$userRule.selector).show(); | |||
123 | }; |
|
128 | }; | |
124 |
|
129 | |||
125 | this.addRule = function (ruleText) { |
|
130 | this.addRule = function (ruleText) { | |
126 | self.showReviewRules(); |
|
131 | self.showReviewRules(); | |
|
132 | self.enabledRules.push(ruleText); | |||
127 | return '<div>- {0}</div>'.format(ruleText) |
|
133 | return '<div>- {0}</div>'.format(ruleText) | |
128 | }; |
|
134 | }; | |
129 |
|
135 | |||
@@ -179,6 +185,7 b' ReviewersController = function () {' | |||||
179 | _gettext('Reviewers picked from source code changes.')) |
|
185 | _gettext('Reviewers picked from source code changes.')) | |
180 | ) |
|
186 | ) | |
181 | } |
|
187 | } | |
|
188 | ||||
182 | if (data.rules.forbid_adding_reviewers) { |
|
189 | if (data.rules.forbid_adding_reviewers) { | |
183 | $('#add_reviewer_input').remove(); |
|
190 | $('#add_reviewer_input').remove(); | |
184 | self.$rulesList.append( |
|
191 | self.$rulesList.append( | |
@@ -186,6 +193,7 b' ReviewersController = function () {' | |||||
186 | _gettext('Adding new reviewers is forbidden.')) |
|
193 | _gettext('Adding new reviewers is forbidden.')) | |
187 | ) |
|
194 | ) | |
188 | } |
|
195 | } | |
|
196 | ||||
189 | if (data.rules.forbid_author_to_review) { |
|
197 | if (data.rules.forbid_author_to_review) { | |
190 | self.forbidReviewUsers.push(data.rules_data.pr_author); |
|
198 | self.forbidReviewUsers.push(data.rules_data.pr_author); | |
191 | self.$rulesList.append( |
|
199 | self.$rulesList.append( | |
@@ -193,6 +201,7 b' ReviewersController = function () {' | |||||
193 | _gettext('Author is not allowed to be a reviewer.')) |
|
201 | _gettext('Author is not allowed to be a reviewer.')) | |
194 | ) |
|
202 | ) | |
195 | } |
|
203 | } | |
|
204 | ||||
196 | if (data.rules.forbid_commit_author_to_review) { |
|
205 | if (data.rules.forbid_commit_author_to_review) { | |
197 |
|
206 | |||
198 | if (data.rules_data.forbidden_users) { |
|
207 | if (data.rules_data.forbidden_users) { | |
@@ -208,6 +217,12 b' ReviewersController = function () {' | |||||
208 | ) |
|
217 | ) | |
209 | } |
|
218 | } | |
210 |
|
219 | |||
|
220 | // we don't have any rules set, so we inform users about it | |||
|
221 | if (self.enabledRules.length === 0) { | |||
|
222 | self.addRule( | |||
|
223 | _gettext('No review rules set.')) | |||
|
224 | } | |||
|
225 | ||||
211 | return self.forbidReviewUsers |
|
226 | return self.forbidReviewUsers | |
212 | }; |
|
227 | }; | |
213 |
|
228 | |||
@@ -347,11 +362,12 b' ReviewersController = function () {' | |||||
347 | members.innerHTML += renderTemplate('reviewMemberEntry', { |
|
362 | members.innerHTML += renderTemplate('reviewMemberEntry', { | |
348 | 'member': reviewer_obj, |
|
363 | 'member': reviewer_obj, | |
349 | 'mandatory': mandatory, |
|
364 | 'mandatory': mandatory, | |
|
365 | 'reasons': reasons, | |||
350 | 'allowed_to_update': true, |
|
366 | 'allowed_to_update': true, | |
351 | 'review_status': 'not_reviewed', |
|
367 | 'review_status': 'not_reviewed', | |
352 | 'review_status_label': _gettext('Not Reviewed'), |
|
368 | 'review_status_label': _gettext('Not Reviewed'), | |
353 |
' |
|
369 | 'user_group': reviewer_obj.user_group, | |
354 | 'create': true |
|
370 | 'create': true, | |
355 | }); |
|
371 | }); | |
356 | tooltipActivate(); |
|
372 | tooltipActivate(); | |
357 | } |
|
373 | } | |
@@ -600,7 +616,7 b' VersionController = function () {' | |||||
600 | var $elem = $(elem); |
|
616 | var $elem = $(elem); | |
601 | var $target = $(target); |
|
617 | var $target = $(target); | |
602 |
|
618 | |||
603 | if ($target.is(':visible')) { |
|
619 | if ($target.is(':visible') || $target.length === 0) { | |
604 | $target.hide(); |
|
620 | $target.hide(); | |
605 | $elem.html($elem.data('toggleOn')) |
|
621 | $elem.html($elem.data('toggleOn')) | |
606 | } else { |
|
622 | } else { |
@@ -10,12 +10,14 b'' | |||||
10 |
|
10 | |||
11 | <%namespace name="base" file="/base/base.mako"/> |
|
11 | <%namespace name="base" file="/base/base.mako"/> | |
12 | <%def name="comment_block(comment, inline=False, active_pattern_entries=None)"> |
|
12 | <%def name="comment_block(comment, inline=False, active_pattern_entries=None)"> | |
13 | <% pr_index_ver = comment.get_index_version(getattr(c, 'versions', [])) %> |
|
13 | ||
|
14 | <% comment_ver = comment.get_index_version(getattr(c, 'versions', [])) %> | |||
14 | <% latest_ver = len(getattr(c, 'versions', [])) %> |
|
15 | <% latest_ver = len(getattr(c, 'versions', [])) %> | |
|
16 | ||||
15 | % if inline: |
|
17 | % if inline: | |
16 |
<% outdated_at_ver = comment.outdated_at_version( |
|
18 | <% outdated_at_ver = comment.outdated_at_version(c.at_version_num) %> | |
17 | % else: |
|
19 | % else: | |
18 |
<% outdated_at_ver = comment.older_than_version( |
|
20 | <% outdated_at_ver = comment.older_than_version(c.at_version_num) %> | |
19 | % endif |
|
21 | % endif | |
20 |
|
22 | |||
21 | <div class="comment |
|
23 | <div class="comment | |
@@ -153,38 +155,38 b'' | |||||
153 | </div> |
|
155 | </div> | |
154 | %endif |
|
156 | %endif | |
155 |
|
157 | |||
156 |
<a class="permalink" href="#comment-${comment.comment_id}"> |
|
158 | <a class="permalink" href="#comment-${comment.comment_id}">¶ #${comment.comment_id}</a> | |
157 |
|
159 | |||
158 | <div class="comment-links-block"> |
|
160 | <div class="comment-links-block"> | |
159 |
|
161 | |||
160 | % if inline: |
|
162 | % if inline: | |
161 | <a class="pr-version-inline" href="${request.current_route_path(_query=dict(version=comment.pull_request_version_id), _anchor='comment-{}'.format(comment.comment_id))}"> |
|
163 | <a class="pr-version-inline" href="${request.current_route_path(_query=dict(version=comment.pull_request_version_id), _anchor='comment-{}'.format(comment.comment_id))}"> | |
162 | % if outdated_at_ver: |
|
164 | % if outdated_at_ver: | |
163 |
<code class="tooltip pr-version-num" title="${_('Outdated comment from pull request version v{0}, latest v{1}').format( |
|
165 | <code class="tooltip pr-version-num" title="${_('Outdated comment from pull request version v{0}, latest v{1}').format(comment_ver, latest_ver)}"> | |
164 |
outdated ${'v{}'.format( |
|
166 | outdated ${'v{}'.format(comment_ver)} | | |
165 | </code> |
|
167 | </code> | |
166 |
% elif |
|
168 | % elif comment_ver: | |
167 |
<code class="tooltip pr-version-num" title="${_('Comment from pull request version v{0}, latest v{1}').format( |
|
169 | <code class="tooltip pr-version-num" title="${_('Comment from pull request version v{0}, latest v{1}').format(comment_ver, latest_ver)}"> | |
168 |
${'v{}'.format( |
|
170 | ${'v{}'.format(comment_ver)} | | |
169 | </code> |
|
171 | </code> | |
170 | % endif |
|
172 | % endif | |
171 | </a> |
|
173 | </a> | |
172 | % else: |
|
174 | % else: | |
173 |
% if |
|
175 | % if comment_ver: | |
174 |
|
176 | |||
175 | % if comment.outdated: |
|
177 | % if comment.outdated: | |
176 | <a class="pr-version" |
|
178 | <a class="pr-version" | |
177 | href="?version=${comment.pull_request_version_id}#comment-${comment.comment_id}" |
|
179 | href="?version=${comment.pull_request_version_id}#comment-${comment.comment_id}" | |
178 | > |
|
180 | > | |
179 |
${_('Outdated comment from pull request version v{0}, latest v{1}').format( |
|
181 | ${_('Outdated comment from pull request version v{0}, latest v{1}').format(comment_ver, latest_ver)} | |
180 | </a> | |
|
182 | </a> | | |
181 | % else: |
|
183 | % else: | |
182 | <a class="tooltip pr-version" |
|
184 | <a class="tooltip pr-version" | |
183 |
title="${_('Comment from pull request version v{0}, latest v{1}').format( |
|
185 | title="${_('Comment from pull request version v{0}, latest v{1}').format(comment_ver, latest_ver)}" | |
184 | 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)}" |
|
186 | href="${h.route_path('pullrequest_show',repo_name=comment.pull_request.target_repo.repo_name,pull_request_id=comment.pull_request.pull_request_id, version=comment.pull_request_version_id)}" | |
185 | > |
|
187 | > | |
186 | <code class="pr-version-num"> |
|
188 | <code class="pr-version-num"> | |
187 |
${'v{}'.format( |
|
189 | ${'v{}'.format(comment_ver)} | |
188 | </code> |
|
190 | </code> | |
189 | </a> | |
|
191 | </a> | | |
190 | % endif |
|
192 | % endif |
@@ -21,8 +21,9 b'' | |||||
21 | ## to speed up lookups cache some functions before the loop |
|
21 | ## to speed up lookups cache some functions before the loop | |
22 | <% |
|
22 | <% | |
23 | active_patterns = h.get_active_pattern_entries(c.repo_name) |
|
23 | active_patterns = h.get_active_pattern_entries(c.repo_name) | |
24 | urlify_commit_message = h.partial(h.urlify_commit_message, active_pattern_entries=active_patterns) |
|
24 | urlify_commit_message = h.partial(h.urlify_commit_message, active_pattern_entries=active_patterns, issues_container=getattr(c, 'referenced_commit_issues', None)) | |
25 | %> |
|
25 | %> | |
|
26 | ||||
26 | %for commit in c.commit_ranges: |
|
27 | %for commit in c.commit_ranges: | |
27 | <tr id="row-${commit.raw_id}" |
|
28 | <tr id="row-${commit.raw_id}" | |
28 | commit_id="${commit.raw_id}" |
|
29 | commit_id="${commit.raw_id}" |
@@ -1,6 +1,10 b'' | |||||
1 | <%text> |
|
1 | <%text> | |
2 | <div style="display: none"> |
|
2 | <div style="display: none"> | |
3 |
|
3 | |||
|
4 | <script> | |||
|
5 | var CG = new ColorGenerator(); | |||
|
6 | </script> | |||
|
7 | ||||
4 | <script id="ejs_gravatarWithUser" type="text/template" class="ejsTemplate"> |
|
8 | <script id="ejs_gravatarWithUser" type="text/template" class="ejsTemplate"> | |
5 |
|
9 | |||
6 | <% |
|
10 | <% | |
@@ -34,10 +38,6 b" var data_hovercard_url = pyroutes.url('h" | |||||
34 |
|
38 | |||
35 | </script> |
|
39 | </script> | |
36 |
|
40 | |||
37 | <script> |
|
|||
38 | var CG = new ColorGenerator(); |
|
|||
39 | </script> |
|
|||
40 |
|
||||
41 | <script id="ejs_reviewMemberEntry" type="text/template" class="ejsTemplate"> |
|
41 | <script id="ejs_reviewMemberEntry" type="text/template" class="ejsTemplate"> | |
42 | <% |
|
42 | <% | |
43 | if (create) { |
|
43 | if (create) { | |
@@ -47,26 +47,24 b' var CG = new ColorGenerator();' | |||||
47 | } |
|
47 | } | |
48 |
|
48 | |||
49 | if (member.user_group && member.user_group.vote_rule) { |
|
49 | if (member.user_group && member.user_group.vote_rule) { | |
50 | var groupStyle = 'border-right: 2px solid '+CG.asRGB(CG.getColor(member.user_group.vote_rule)); |
|
50 | var reviewGroup = '<i class="icon-user-group"></i>'; | |
|
51 | var reviewGroupColor = CG.asRGB(CG.getColor(member.user_group.vote_rule)); | |||
51 | } else { |
|
52 | } else { | |
52 | var groupStyle = 'border-right: 2px solid transparent'; |
|
53 | var reviewGroup = null; | |
|
54 | var reviewGroupColor = 'transparent'; | |||
53 | } |
|
55 | } | |
54 | %> |
|
56 | %> | |
55 |
|
57 | |||
56 |
< |
|
58 | <tr id="reviewer_<%= member.user_id %>" class="reviewer_entry" tooltip="Review Group" data-reviewer-user-id="<%= member.user_id %>"> | |
57 |
|
59 | |||
58 | <div class="reviewers_member"> |
|
60 | <td style="width: 20px"> | |
59 | <div class="reviewer_status tooltip" title="<%= review_status_label %>"> |
|
61 | <div class="reviewer_status tooltip" title="<%= review_status_label %>"> | |
60 | <i class="icon-circle review-status-<%= review_status %>"></i> |
|
62 | <i class="icon-circle review-status-<%= review_status %>"></i> | |
|
63 | </div> | |||
|
64 | </td> | |||
61 |
|
65 | |||
62 |
|
|
66 | <td> | |
63 |
|
|
67 | <div id="reviewer_<%= member.user_id %>_name" class="reviewer_name"> | |
64 | <% if (mandatory) { %> |
|
|||
65 | <div class="reviewer_member_mandatory tooltip" title="Mandatory reviewer"> |
|
|||
66 | <i class="icon-lock"></i> |
|
|||
67 | </div> |
|
|||
68 | <% } %> |
|
|||
69 |
|
||||
70 | <%- |
|
68 | <%- | |
71 | renderTemplate('gravatarWithUser', { |
|
69 | renderTemplate('gravatarWithUser', { | |
72 | 'size': 16, |
|
70 | 'size': 16, | |
@@ -78,11 +76,43 b' var CG = new ColorGenerator();' | |||||
78 | 'gravatar_url': member.gravatar_link |
|
76 | 'gravatar_url': member.gravatar_link | |
79 | }) |
|
77 | }) | |
80 | %> |
|
78 | %> | |
|
79 | <span class="tooltip presence-state" style="display: none" title="This users is currently at this page"> | |||
|
80 | <i class="icon-eye" style="color: #0ac878"></i> | |||
|
81 | </span> | |||
81 | </div> |
|
82 | </div> | |
|
83 | </td> | |||
|
84 | ||||
|
85 | <td style="width: 10px"> | |||
|
86 | <% if (reviewGroup !== null) { %> | |||
|
87 | <span class="tooltip" title="Member of review group from rule: `<%= member.user_group.name %>`" style="color: <%= reviewGroupColor %>"> | |||
|
88 | <%- reviewGroup %> | |||
|
89 | </span> | |||
|
90 | <% } %> | |||
|
91 | </td> | |||
82 |
|
92 | |||
|
93 | <% if (mandatory) { %> | |||
|
94 | <td style="text-align: right;width: 10px;"> | |||
|
95 | <div class="reviewer_member_mandatory tooltip" title="Mandatory reviewer"> | |||
|
96 | <i class="icon-lock"></i> | |||
|
97 | </div> | |||
|
98 | </td> | |||
|
99 | ||||
|
100 | <% } else { %> | |||
|
101 | <td> | |||
|
102 | <% if (allowed_to_update) { %> | |||
|
103 | <div class="reviewer_member_remove action_button" onclick="reviewersController.removeReviewMember(<%= member.user_id %>, true)" style="visibility: <%= edit_visibility %>;"> | |||
|
104 | <i class="icon-remove"></i> | |||
|
105 | </div> | |||
|
106 | <% } %> | |||
|
107 | </td> | |||
|
108 | <% } %> | |||
|
109 | ||||
|
110 | </tr> | |||
|
111 | ||||
|
112 | <tr> | |||
|
113 | <td colspan="4" style="display: none" class="pr-user-rule-container"> | |||
83 | <input type="hidden" name="__start__" value="reviewer:mapping"> |
|
114 | <input type="hidden" name="__start__" value="reviewer:mapping"> | |
84 |
|
115 | |||
85 |
|
||||
86 | <%if (member.user_group && member.user_group.vote_rule) {%> |
|
116 | <%if (member.user_group && member.user_group.vote_rule) { %> | |
87 | <div class="reviewer_reason"> |
|
117 | <div class="reviewer_reason"> | |
88 |
|
118 | |||
@@ -113,24 +143,11 b' var CG = new ColorGenerator();' | |||||
113 | <input type="hidden" name="mandatory" value="<%= mandatory %>"/> |
|
143 | <input type="hidden" name="mandatory" value="<%= mandatory %>"/> | |
114 |
|
144 | |||
115 | <input type="hidden" name="__end__" value="reviewer:mapping"> |
|
145 | <input type="hidden" name="__end__" value="reviewer:mapping"> | |
116 |
|
146 | </td> | ||
117 | <% if (mandatory) { %> |
|
147 | </tr> | |
118 | <div class="reviewer_member_mandatory_remove" style="visibility: <%= edit_visibility %>;"> |
|
|||
119 | <i class="icon-remove"></i> |
|
|||
120 | </div> |
|
|||
121 | <% } else { %> |
|
|||
122 | <% if (allowed_to_update) { %> |
|
|||
123 | <div class="reviewer_member_remove action_button" onclick="reviewersController.removeReviewMember(<%= member.user_id %>, true)" style="visibility: <%= edit_visibility %>;"> |
|
|||
124 | <i class="icon-remove" ></i> |
|
|||
125 | </div> |
|
|||
126 | <% } %> |
|
|||
127 | <% } %> |
|
|||
128 | </div> |
|
|||
129 | </li> |
|
|||
130 |
|
148 | |||
131 | </script> |
|
149 | </script> | |
132 |
|
150 | |||
133 |
|
||||
134 | <script id="ejs_commentVersion" type="text/template" class="ejsTemplate"> |
|
151 | <script id="ejs_commentVersion" type="text/template" class="ejsTemplate"> | |
135 |
|
152 | |||
136 | <% |
|
153 | <% | |
@@ -158,7 +175,6 b' if (show_disabled) {' | |||||
158 |
|
175 | |||
159 | </script> |
|
176 | </script> | |
160 |
|
177 | |||
161 |
|
||||
162 | </div> |
|
178 | </div> | |
163 |
|
179 | |||
164 | <script> |
|
180 | <script> |
@@ -360,13 +360,13 b' text_monospace = "\'Menlo\', \'Liberation M' | |||||
360 |
|
360 | |||
361 | div.markdown-block ul.checkbox li, div.markdown-block ol.checkbox li { |
|
361 | div.markdown-block ul.checkbox li, div.markdown-block ol.checkbox li { | |
362 | list-style: none !important; |
|
362 | list-style: none !important; | |
363 |
margin: |
|
363 | margin: 0px !important; | |
364 | padding: 0 !important |
|
364 | padding: 0 !important | |
365 | } |
|
365 | } | |
366 |
|
366 | |||
367 | div.markdown-block ul li, div.markdown-block ol li { |
|
367 | div.markdown-block ul li, div.markdown-block ol li { | |
368 | list-style: disc !important; |
|
368 | list-style: disc !important; | |
369 |
margin: |
|
369 | margin: 0px !important; | |
370 | padding: 0 !important |
|
370 | padding: 0 !important | |
371 | } |
|
371 | } | |
372 |
|
372 |
This diff has been collapsed as it changes many lines, (1139 lines changed) Show them Hide them | |||||
@@ -21,7 +21,120 b'' | |||||
21 | ${self.repo_menu(active='showpullrequest')} |
|
21 | ${self.repo_menu(active='showpullrequest')} | |
22 | </%def> |
|
22 | </%def> | |
23 |
|
23 | |||
|
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 | ||||
24 | <%def name="main()"> |
|
132 | <%def name="main()"> | |
|
133 | ## Container to gather extracted Tickets | |||
|
134 | <% | |||
|
135 | c.referenced_commit_issues = [] | |||
|
136 | c.referenced_desc_issues = [] | |||
|
137 | %> | |||
25 |
|
138 | |||
26 | <script type="text/javascript"> |
|
139 | <script type="text/javascript"> | |
27 | // TODO: marcink switch this to pyroutes |
|
140 | // TODO: marcink switch this to pyroutes | |
@@ -79,7 +192,7 b'' | |||||
79 | </div> |
|
192 | </div> | |
80 |
|
193 | |||
81 | <div id="pr-desc" class="input" title="${_('Rendered using {} renderer').format(c.renderer)}"> |
|
194 | <div id="pr-desc" class="input" title="${_('Rendered using {} renderer').format(c.renderer)}"> | |
82 | ${h.render(c.pull_request.description, renderer=c.renderer, repo_name=c.repo_name)} |
|
195 | ${h.render(c.pull_request.description, renderer=c.renderer, repo_name=c.repo_name, issues_container=c.referenced_desc_issues)} | |
83 | </div> |
|
196 | </div> | |
84 |
|
197 | |||
85 | <div id="pr-desc-edit" class="input textarea" style="display: none;"> |
|
198 | <div id="pr-desc-edit" class="input textarea" style="display: none;"> | |
@@ -89,29 +202,6 b'' | |||||
89 |
|
202 | |||
90 | <div id="summary" class="fields pr-details-content"> |
|
203 | <div id="summary" class="fields pr-details-content"> | |
91 |
|
204 | |||
92 | ## review |
|
|||
93 | <div class="field"> |
|
|||
94 | <div class="label-pr-detail"> |
|
|||
95 | <label>${_('Review status')}:</label> |
|
|||
96 | </div> |
|
|||
97 | <div class="input"> |
|
|||
98 | %if c.pull_request_review_status: |
|
|||
99 | <div class="tag status-tag-${c.pull_request_review_status}"> |
|
|||
100 | <i class="icon-circle review-status-${c.pull_request_review_status}"></i> |
|
|||
101 | <span class="changeset-status-lbl"> |
|
|||
102 | %if c.pull_request.is_closed(): |
|
|||
103 | ${_('Closed')}, |
|
|||
104 | %endif |
|
|||
105 |
|
||||
106 | ${h.commit_status_lbl(c.pull_request_review_status)} |
|
|||
107 |
|
||||
108 | </span> |
|
|||
109 | </div> |
|
|||
110 | - ${_ungettext('calculated based on {} reviewer vote', 'calculated based on {} reviewers votes', len(c.pull_request_reviewers)).format(len(c.pull_request_reviewers))} |
|
|||
111 | %endif |
|
|||
112 | </div> |
|
|||
113 | </div> |
|
|||
114 |
|
||||
115 | ## source |
|
205 | ## source | |
116 | <div class="field"> |
|
206 | <div class="field"> | |
117 | <div class="label-pr-detail"> |
|
207 | <div class="label-pr-detail"> | |
@@ -231,7 +321,7 b'' | |||||
231 | </code> |
|
321 | </code> | |
232 | </td> |
|
322 | </td> | |
233 | <td> |
|
323 | <td> | |
234 |
<input ${('checked="checked"' if c.from_version_ |
|
324 | <input ${('checked="checked"' if c.from_version_index == ver_pr else '')} class="compare-radio-button" type="radio" name="ver_source" value="${ver_pr or 'latest'}" data-ver-pos="${ver_pos}"/> | |
235 | <input ${('checked="checked"' if c.at_version_num == ver_pr else '')} class="compare-radio-button" type="radio" name="ver_target" value="${ver_pr or 'latest'}" data-ver-pos="${ver_pos}"/> |
|
325 | <input ${('checked="checked"' if c.at_version_num == ver_pr else '')} class="compare-radio-button" type="radio" name="ver_target" value="${ver_pr or 'latest'}" data-ver-pos="${ver_pos}"/> | |
236 | </td> |
|
326 | </td> | |
237 | <td> |
|
327 | <td> | |
@@ -281,8 +371,6 b'' | |||||
281 | </div> |
|
371 | </div> | |
282 |
|
372 | |||
283 |
|
373 | |||
284 |
|
||||
285 |
|
||||
286 | </div> |
|
374 | </div> | |
287 |
|
375 | |||
288 | </div> |
|
376 | </div> | |
@@ -339,9 +427,9 b'' | |||||
339 | <div class="compare_view_commits_title"> |
|
427 | <div class="compare_view_commits_title"> | |
340 | % if not c.compare_mode: |
|
428 | % if not c.compare_mode: | |
341 |
|
429 | |||
342 |
% if c.at_version_ |
|
430 | % if c.at_version_index: | |
343 | <h4> |
|
431 | <h4> | |
344 |
${_('Showing changes at v |
|
432 | ${_('Showing changes at v{}, commenting is disabled.').format(c.at_version_index)} | |
345 | </h4> |
|
433 | </h4> | |
346 | % endif |
|
434 | % endif | |
347 |
|
435 | |||
@@ -394,10 +482,11 b'' | |||||
394 | </div> |
|
482 | </div> | |
395 |
|
483 | |||
396 | % if not c.missing_commits: |
|
484 | % if not c.missing_commits: | |
|
485 | ## COMPARE RANGE DIFF MODE | |||
397 | % if c.compare_mode: |
|
486 | % if c.compare_mode: | |
398 | % if c.at_version: |
|
487 | % if c.at_version: | |
399 | <h4> |
|
488 | <h4> | |
400 |
${_('Commits and changes between v{ver_from} and {ver_to} of this pull request, commenting is disabled').format(ver_from=c.from_version_ |
|
489 | ${_('Commits and changes between v{ver_from} and {ver_to} of this pull request, commenting is disabled').format(ver_from=c.from_version_index, ver_to=c.at_version_index if c.at_version_index else 'latest')}: | |
401 | </h4> |
|
490 | </h4> | |
402 |
|
491 | |||
403 | <div class="subtitle-compare"> |
|
492 | <div class="subtitle-compare"> | |
@@ -452,7 +541,7 b'' | |||||
452 | </td> |
|
541 | </td> | |
453 | <td class="mid td-description"> |
|
542 | <td class="mid td-description"> | |
454 | <div class="log-container truncate-wrap"> |
|
543 | <div class="log-container truncate-wrap"> | |
455 | <div class="message truncate" id="c-${commit.raw_id}" data-message-raw="${commit.message}">${h.urlify_commit_message(commit.message, c.repo_name)}</div> |
|
544 | <div class="message truncate" id="c-${commit.raw_id}" data-message-raw="${commit.message}">${h.urlify_commit_message(commit.message, c.repo_name, issues_container=c.referenced_commit_issues)}</div> | |
456 | </div> |
|
545 | </div> | |
457 | </td> |
|
546 | </td> | |
458 | </tr> |
|
547 | </tr> | |
@@ -463,21 +552,13 b'' | |||||
463 |
|
552 | |||
464 | % endif |
|
553 | % endif | |
465 |
|
554 | |||
|
555 | ## Regular DIFF | |||
466 | % else: |
|
556 | % else: | |
467 | <%include file="/compare/compare_commits.mako" /> |
|
557 | <%include file="/compare/compare_commits.mako" /> | |
468 | % endif |
|
558 | % endif | |
469 |
|
559 | |||
470 | <div class="cs_files"> |
|
560 | <div class="cs_files"> | |
471 | <%namespace name="cbdiffs" file="/codeblocks/diffs.mako"/> |
|
561 | <%namespace name="cbdiffs" file="/codeblocks/diffs.mako"/> | |
472 | % if c.at_version: |
|
|||
473 | <% c.inline_cnt = len(c.inline_versions[c.at_version_num]['display']) %> |
|
|||
474 | <% c.inline_comments_flat = c.inline_versions[c.at_version_num]['display'] %> |
|
|||
475 | <% c.comments = c.comment_versions[c.at_version_num]['display'] %> |
|
|||
476 | % else: |
|
|||
477 | <% c.inline_cnt = len(c.inline_versions[c.at_version_num]['until']) %> |
|
|||
478 | <% c.inline_comments_flat = c.inline_versions[c.at_version_num]['until'] %> |
|
|||
479 | <% c.comments = c.comment_versions[c.at_version_num]['until'] %> |
|
|||
480 | % endif |
|
|||
481 |
|
562 | |||
482 | <% |
|
563 | <% | |
483 | pr_menu_data = { |
|
564 | pr_menu_data = { | |
@@ -524,7 +605,7 b'' | |||||
524 | ## comments heading with count |
|
605 | ## comments heading with count | |
525 | <div class="comments-heading"> |
|
606 | <div class="comments-heading"> | |
526 | <i class="icon-comment"></i> |
|
607 | <i class="icon-comment"></i> | |
527 | ${_('Comments')} ${len(c.comments)} |
|
608 | ${_('General Comments')} ${len(c.comments)} | |
528 | </div> |
|
609 | </div> | |
529 |
|
610 | |||
530 | ## render general comments |
|
611 | ## render general comments | |
@@ -561,6 +642,354 b'' | |||||
561 | % endif |
|
642 | % endif | |
562 | </div> |
|
643 | </div> | |
563 |
|
644 | |||
|
645 | ||||
|
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 | ||||
|
736 | <aside class="right-sidebar right-sidebar-expanded" id="pr-nav-sticky" style="display: none"> | |||
|
737 | <div class="sidenav navbar__inner" > | |||
|
738 | ## TOGGLE | |||
|
739 | <div class="sidebar-toggle" onclick="toggleSidebar(); return false"> | |||
|
740 | <a href="#toggleSidebar"> | |||
|
741 | ||||
|
742 | </a> | |||
|
743 | </div> | |||
|
744 | ||||
|
745 | ## CONTENT | |||
|
746 | <div class="sidebar-content"> | |||
|
747 | ||||
|
748 | ## RULES SUMMARY/RULES | |||
|
749 | <div class="sidebar-element clear-both"> | |||
|
750 | ||||
|
751 | <div class="tooltip right-sidebar-collapsed-state" style="display: none" onclick="toggleSidebar(); return false" title="${_('Reviewers')}"> | |||
|
752 | <i class="icon-circle review-status-${c.pull_request_review_status}"></i> | |||
|
753 | ${len(c.allowed_reviewers)} | |||
|
754 | </div> | |||
|
755 | ||||
|
756 | ## REVIEW RULES | |||
|
757 | <div id="review_rules" style="display: none" class=""> | |||
|
758 | <div class="right-sidebar-expanded-state pr-details-title"> | |||
|
759 | <span class="sidebar-heading"> | |||
|
760 | ${_('Reviewer rules')} | |||
|
761 | </span> | |||
|
762 | ||||
|
763 | </div> | |||
|
764 | <div class="pr-reviewer-rules"> | |||
|
765 | ## review rules will be appended here, by default reviewers logic | |||
|
766 | </div> | |||
|
767 | <input id="review_data" type="hidden" name="review_data" value=""> | |||
|
768 | </div> | |||
|
769 | ||||
|
770 | ## REVIEWERS | |||
|
771 | <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))}"> | |||
|
773 | <i class="icon-circle review-status-${c.pull_request_review_status}"></i> | |||
|
774 | ${_('Reviewers')} | |||
|
775 | </span> | |||
|
776 | %if c.allowed_to_update: | |||
|
777 | <span id="open_edit_reviewers" class="block-right action_button last-item">${_('Edit')}</span> | |||
|
778 | <span id="close_edit_reviewers" class="block-right action_button last-item" style="display: none;">${_('Close')}</span> | |||
|
779 | %else: | |||
|
780 | <span id="open_edit_reviewers" class="block-right action_button last-item">${_('Show rules')}</span> | |||
|
781 | <span id="close_edit_reviewers" class="block-right action_button last-item" style="display: none;">${_('Close')}</span> | |||
|
782 | %endif | |||
|
783 | </div> | |||
|
784 | ||||
|
785 | <div id="reviewers" class="right-sidebar-expanded-state pr-details-content reviewers"> | |||
|
786 | ||||
|
787 | ## members redering block | |||
|
788 | <input type="hidden" name="__start__" value="review_members:sequence"> | |||
|
789 | ||||
|
790 | <table id="review_members" class="group_members"> | |||
|
791 | ## This content is loaded via JS and ReviewersPanel | |||
|
792 | </table> | |||
|
793 | ||||
|
794 | <input type="hidden" name="__end__" value="review_members:sequence"> | |||
|
795 | ## end members redering block | |||
|
796 | ||||
|
797 | %if not c.pull_request.is_closed(): | |||
|
798 | <div id="add_reviewer" class="ac" style="display: none;"> | |||
|
799 | %if c.allowed_to_update: | |||
|
800 | % if not c.forbid_adding_reviewers: | |||
|
801 | <div id="add_reviewer_input" class="reviewer_ac"> | |||
|
802 | ${h.text('user', class_='ac-input', placeholder=_('Add reviewer or reviewer group'))} | |||
|
803 | <div id="reviewers_container"></div> | |||
|
804 | </div> | |||
|
805 | % endif | |||
|
806 | <div class="pull-right"> | |||
|
807 | <button id="update_pull_request" class="btn btn-small no-margin">${_('Save Changes')}</button> | |||
|
808 | </div> | |||
|
809 | %endif | |||
|
810 | </div> | |||
|
811 | %endif | |||
|
812 | </div> | |||
|
813 | </div> | |||
|
814 | ||||
|
815 | ## ## OBSERVERS | |||
|
816 | ## <div class="sidebar-element clear-both"> | |||
|
817 | ## <div class="tooltip right-sidebar-collapsed-state" style="display: none" onclick="toggleSidebar(); return false" title="${_('Observers')}"> | |||
|
818 | ## <i class="icon-eye"></i> | |||
|
819 | ## 0 | |||
|
820 | ## </div> | |||
|
821 | ## | |||
|
822 | ## <div class="right-sidebar-expanded-state pr-details-title"> | |||
|
823 | ## <span class="sidebar-heading"> | |||
|
824 | ## <i class="icon-eye"></i> | |||
|
825 | ## ${_('Observers')} | |||
|
826 | ## </span> | |||
|
827 | ## </div> | |||
|
828 | ## <div class="right-sidebar-expanded-state pr-details-content"> | |||
|
829 | ## No observers | |||
|
830 | ## </div> | |||
|
831 | ## </div> | |||
|
832 | ||||
|
833 | ## TODOs | |||
|
834 | <div class="sidebar-element clear-both"> | |||
|
835 | <div class="tooltip right-sidebar-collapsed-state" style="display: none" onclick="toggleSidebar(); return false" title="TODOs"> | |||
|
836 | <i class="icon-flag-filled"></i> | |||
|
837 | <span id="todos-count">${len(c.unresolved_comments)}</span> | |||
|
838 | </div> | |||
|
839 | ||||
|
840 | <div class="right-sidebar-expanded-state pr-details-title"> | |||
|
841 | ## Only show unresolved, that is only what matters | |||
|
842 | <span class="sidebar-heading noselect" onclick="refreshTODOs(); return false"> | |||
|
843 | <i class="icon-flag-filled"></i> | |||
|
844 | TODOs | |||
|
845 | </span> | |||
|
846 | ||||
|
847 | % if not c.at_version: | |||
|
848 | % if c.resolved_comments: | |||
|
849 | <span class="block-right action_button last-item noselect" onclick="$('.unresolved-todo-text').toggle(); return versionController.toggleElement(this, '.resolved-todo');" data-toggle-on="Show resolved" data-toggle-off="Hide resolved">Show resolved</span> | |||
|
850 | % else: | |||
|
851 | <span class="block-right last-item noselect">Show resolved</span> | |||
|
852 | % endif | |||
|
853 | % endif | |||
|
854 | </div> | |||
|
855 | ||||
|
856 | <div class="right-sidebar-expanded-state pr-details-content"> | |||
|
857 | ||||
|
858 | % if c.at_version: | |||
|
859 | <table> | |||
|
860 | <tr> | |||
|
861 | <td class="unresolved-todo-text">${_('TODOs unavailable when browsing versions')}.</td> | |||
|
862 | </tr> | |||
|
863 | </table> | |||
|
864 | % else: | |||
|
865 | % if c.unresolved_comments + c.resolved_comments: | |||
|
866 | ${comments_table(c.unresolved_comments + c.resolved_comments, len(c.unresolved_comments), todo_comments=True)} | |||
|
867 | % else: | |||
|
868 | <table> | |||
|
869 | <tr> | |||
|
870 | <td> | |||
|
871 | ${_('No TODOs yet')} | |||
|
872 | </td> | |||
|
873 | </tr> | |||
|
874 | </table> | |||
|
875 | % endif | |||
|
876 | % endif | |||
|
877 | </div> | |||
|
878 | </div> | |||
|
879 | ||||
|
880 | ## COMMENTS | |||
|
881 | <div class="sidebar-element clear-both"> | |||
|
882 | <div class="tooltip right-sidebar-collapsed-state" style="display: none" onclick="toggleSidebar(); return false" title="${_('Comments')}"> | |||
|
883 | <i class="icon-comment" style="color: #949494"></i> | |||
|
884 | <span id="comments-count">${len(c.inline_comments_flat+c.comments)}</span> | |||
|
885 | </div> | |||
|
886 | ||||
|
887 | <div class="right-sidebar-expanded-state pr-details-title"> | |||
|
888 | <span class="sidebar-heading noselect" onclick="refreshComments(); return false"> | |||
|
889 | <i class="icon-comment" style="color: #949494"></i> | |||
|
890 | ${_('Comments')} | |||
|
891 | ||||
|
892 | ## % if outdated_comm_count_ver: | |||
|
893 | ## <a href="#" onclick="showOutdated(); Rhodecode.comments.nextOutdatedComment(); return false;"> | |||
|
894 | ## (${_("{} Outdated").format(outdated_comm_count_ver)}) | |||
|
895 | ## </a> | |||
|
896 | ## <a href="#" class="showOutdatedComments" onclick="showOutdated(this); return false;"> | ${_('show outdated')}</a> | |||
|
897 | ## <a href="#" class="hideOutdatedComments" style="display: none" onclick="hideOutdated(this); return false;"> | ${_('hide outdated')}</a> | |||
|
898 | ||||
|
899 | ## % else: | |||
|
900 | ## (${_("{} Outdated").format(outdated_comm_count_ver)}) | |||
|
901 | ## % endif | |||
|
902 | ||||
|
903 | </span> | |||
|
904 | ||||
|
905 | % if outdated_comm_count_ver: | |||
|
906 | <span class="block-right action_button last-item noselect" onclick="return versionController.toggleElement(this, '.hidden-comment');" data-toggle-on="Show outdated" data-toggle-off="Hide outdated">Show outdated</span> | |||
|
907 | % else: | |||
|
908 | <span class="block-right last-item noselect">Show hidden</span> | |||
|
909 | % endif | |||
|
910 | ||||
|
911 | </div> | |||
|
912 | ||||
|
913 | <div class="right-sidebar-expanded-state pr-details-content"> | |||
|
914 | % if c.inline_comments_flat + c.comments: | |||
|
915 | ${comments_table(c.inline_comments_flat + c.comments, len(c.inline_comments_flat+c.comments))} | |||
|
916 | % else: | |||
|
917 | <table> | |||
|
918 | <tr> | |||
|
919 | <td> | |||
|
920 | ${_('No Comments yet')} | |||
|
921 | </td> | |||
|
922 | </tr> | |||
|
923 | </table> | |||
|
924 | % endif | |||
|
925 | </div> | |||
|
926 | ||||
|
927 | </div> | |||
|
928 | ||||
|
929 | ## Referenced Tickets | |||
|
930 | <div class="sidebar-element clear-both"> | |||
|
931 | <div class="tooltip right-sidebar-collapsed-state" style="display: none" onclick="toggleSidebar(); return false" title="${_('Referenced Tickets')}"> | |||
|
932 | <i class="icon-info-circled"></i> | |||
|
933 | ${(len(c.referenced_desc_issues) + len(c.referenced_commit_issues))} | |||
|
934 | </div> | |||
|
935 | ||||
|
936 | <div class="right-sidebar-expanded-state pr-details-title"> | |||
|
937 | <span class="sidebar-heading"> | |||
|
938 | <i class="icon-info-circled"></i> | |||
|
939 | ${_('Referenced Tickets')} | |||
|
940 | </span> | |||
|
941 | </div> | |||
|
942 | <div class="right-sidebar-expanded-state pr-details-content"> | |||
|
943 | <table> | |||
|
944 | ||||
|
945 | <tr><td><code>${_('Pull Request Description')}</code></td></tr> | |||
|
946 | % if c.referenced_desc_issues: | |||
|
947 | % for ticket_dict in c.referenced_desc_issues: | |||
|
948 | <tr> | |||
|
949 | <td> | |||
|
950 | <a href="${ticket_dict.get('url')}"> | |||
|
951 | ${ticket_dict.get('id')} | |||
|
952 | </a> | |||
|
953 | </td> | |||
|
954 | </tr> | |||
|
955 | % endfor | |||
|
956 | % else: | |||
|
957 | <tr> | |||
|
958 | <td> | |||
|
959 | ${_('No Ticket data found.')} | |||
|
960 | </td> | |||
|
961 | </tr> | |||
|
962 | % endif | |||
|
963 | ||||
|
964 | <tr><td style="padding-top: 10px"><code>${_('Commit Messages')}</code></td></tr> | |||
|
965 | % if c.referenced_commit_issues: | |||
|
966 | % for ticket_dict in c.referenced_commit_issues: | |||
|
967 | <tr> | |||
|
968 | <td> | |||
|
969 | <a href="${ticket_dict.get('url')}"> | |||
|
970 | ${ticket_dict.get('id')} | |||
|
971 | </a> | |||
|
972 | </td> | |||
|
973 | </tr> | |||
|
974 | % endfor | |||
|
975 | % else: | |||
|
976 | <tr> | |||
|
977 | <td> | |||
|
978 | ${_('No Ticket data found.')} | |||
|
979 | </td> | |||
|
980 | </tr> | |||
|
981 | % endif | |||
|
982 | </table> | |||
|
983 | ||||
|
984 | </div> | |||
|
985 | </div> | |||
|
986 | ||||
|
987 | </div> | |||
|
988 | ||||
|
989 | </div> | |||
|
990 | </aside> | |||
|
991 | ||||
|
992 | ## This JS needs to be at the end | |||
564 | <script type="text/javascript"> |
|
993 | <script type="text/javascript"> | |
565 |
|
994 | |||
566 | versionController = new VersionController(); |
|
995 | versionController = new VersionController(); | |
@@ -571,6 +1000,61 b'' | |||||
571 |
|
1000 | |||
572 | updateController = new UpdatePrController(); |
|
1001 | updateController = new UpdatePrController(); | |
573 |
|
1002 | |||
|
1003 | /** leak object to top level scope **/ | |||
|
1004 | window.PullRequestPresenceController; | |||
|
1005 | ||||
|
1006 | (function () { | |||
|
1007 | "use strict"; | |||
|
1008 | ||||
|
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 | ||||
574 | $(function () { |
|
1058 | $(function () { | |
575 |
|
1059 | |||
576 | // custom code mirror |
|
1060 | // custom code mirror | |
@@ -616,6 +1100,8 b'' | |||||
616 | closeButton: $('#close_edit_reviewers'), |
|
1100 | closeButton: $('#close_edit_reviewers'), | |
617 | addButton: $('#add_reviewer'), |
|
1101 | addButton: $('#add_reviewer'), | |
618 | removeButtons: $('.reviewer_member_remove,.reviewer_member_mandatory_remove'), |
|
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}, | |||
619 |
|
1105 | |||
620 | init: function () { |
|
1106 | init: function () { | |
621 | var self = this; |
|
1107 | var self = this; | |
@@ -624,24 +1110,50 b'' | |||||
624 | }); |
|
1110 | }); | |
625 | this.closeButton.on('click', function (e) { |
|
1111 | this.closeButton.on('click', function (e) { | |
626 | self.close(); |
|
1112 | self.close(); | |
|
1113 | self.renderReviewers(); | |||
627 | }); |
|
1114 | }); | |
|
1115 | ||||
|
1116 | self.renderReviewers(); | |||
|
1117 | ||||
|
1118 | }, | |||
|
1119 | ||||
|
1120 | renderReviewers: function () { | |||
|
1121 | ||||
|
1122 | $('#review_members').html('') | |||
|
1123 | $.each(this.setReviewers.reviewers, function (key, val) { | |||
|
1124 | var member = val; | |||
|
1125 | ||||
|
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 | ||||
628 | }, |
|
1141 | }, | |
629 |
|
1142 | |||
630 | edit: function (event) { |
|
1143 | edit: function (event) { | |
631 | this.editButton.hide(); |
|
1144 | this.editButton.hide(); | |
632 | this.closeButton.show(); |
|
1145 | this.closeButton.show(); | |
633 | this.addButton.show(); |
|
1146 | this.addButton.show(); | |
634 | this.removeButtons.css('visibility', 'visible'); |
|
1147 | $(this.removeButtons.selector).css('visibility', 'visible'); | |
635 | // review rules |
|
1148 | // review rules | |
636 | reviewersController.loadReviewRules( |
|
1149 | reviewersController.loadReviewRules(this.reviewRules); | |
637 | ${c.pull_request.reviewer_data_json | n}); |
|
|||
638 | }, |
|
1150 | }, | |
639 |
|
1151 | |||
640 | close: function (event) { |
|
1152 | close: function (event) { | |
641 | this.editButton.show(); |
|
1153 | this.editButton.show(); | |
642 | this.closeButton.hide(); |
|
1154 | this.closeButton.hide(); | |
643 | this.addButton.hide(); |
|
1155 | this.addButton.hide(); | |
644 | this.removeButtons.css('visibility', 'hidden'); |
|
1156 | $(this.removeButtons.selector).css('visibility', 'hidden'); | |
645 | // hide review rules |
|
1157 | // hide review rules | |
646 | reviewersController.hideReviewRules() |
|
1158 | reviewersController.hideReviewRules() | |
647 | } |
|
1159 | } | |
@@ -678,6 +1190,75 b'' | |||||
678 | ); |
|
1190 | ); | |
679 | }; |
|
1191 | }; | |
680 |
|
1192 | |||
|
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 | ||||
681 | closePullRequest = function (status) { |
|
1262 | closePullRequest = function (status) { | |
682 | if (!confirm(_gettext('Are you sure to close this pull request without merging?'))) { |
|
1263 | if (!confirm(_gettext('Are you sure to close this pull request without merging?'))) { | |
683 | return false; |
|
1264 | return false; | |
@@ -771,441 +1352,91 b'' | |||||
771 |
|
1352 | |||
772 | }) |
|
1353 | }) | |
773 |
|
1354 | |||
774 | </script> |
|
1355 | $(document).ready(function () { | |
775 |
|
||||
776 |
|
||||
777 | ### NAVBOG RIGHT |
|
|||
778 | <style> |
|
|||
779 |
|
||||
780 | .right-sidebar { |
|
|||
781 | position: fixed; |
|
|||
782 | top: 0px; |
|
|||
783 | bottom: 0; |
|
|||
784 | right: 0; |
|
|||
785 |
|
||||
786 | background: #fafafa; |
|
|||
787 | z-index: 200; |
|
|||
788 | } |
|
|||
789 |
|
||||
790 | .right-sidebar { |
|
|||
791 | border-left: 1px solid #dbdbdb; |
|
|||
792 | } |
|
|||
793 |
|
||||
794 | .right-sidebar.right-sidebar-expanded { |
|
|||
795 | width: 320px; |
|
|||
796 | overflow: scroll; |
|
|||
797 | } |
|
|||
798 |
|
||||
799 | .right-sidebar.right-sidebar-collapsed { |
|
|||
800 | width: 62px; |
|
|||
801 | padding: 0; |
|
|||
802 | display: block; |
|
|||
803 | overflow: hidden; |
|
|||
804 | } |
|
|||
805 |
|
||||
806 | .sidenav { |
|
|||
807 | float: right; |
|
|||
808 | will-change: min-height; |
|
|||
809 | background: #fafafa; |
|
|||
810 | width: 100%; |
|
|||
811 | } |
|
|||
812 |
|
1356 | |||
813 | .sidebar-toggle { |
|
1357 | var $sideBar = $('.right-sidebar'); | |
814 | height: 30px; |
|
1358 | var marginExpVal = '320' | |
815 | text-align: center; |
|
1359 | var marginColVal = '50' | |
816 | margin: 15px 0 0 0; |
|
1360 | var marginExpanded = {'margin': '0 {0}px 0 0'.format(marginExpVal)}; | |
817 | } |
|
1361 | var marginCollapsed = {'margin': '0 {0}px 0 0'.format(marginColVal)}; | |
818 | .sidebar-toggle a { |
|
1362 | var marginExpandedHeader = {'margin': '0 -{0}px 0 0'.format(marginExpVal), 'z-index': 10000}; | |
819 |
|
1363 | var marginCollapsedHeader = {'margin': '0 -{0}px 0 0'.format(marginColVal), 'z-index': 10000}; | ||
820 | } |
|
|||
821 |
|
||||
822 | .sidebar-content { |
|
|||
823 | margin-left: 5px; |
|
|||
824 | margin-right: 5px; |
|
|||
825 | } |
|
|||
826 |
|
||||
827 | .sidebar-heading { |
|
|||
828 | font-size: 1.2em; |
|
|||
829 | font-weight: 700; |
|
|||
830 | margin-top: 10px; |
|
|||
831 | } |
|
|||
832 |
|
1364 | |||
833 | .sidebar-element { |
|
1365 | var updateStickyHeader = function() { | |
834 | margin-top: 20px; |
|
1366 | if (window.updateSticky !== undefined) { | |
|
1367 | // potentially our comments change the active window size, so we | |||
|
1368 | // notify sticky elements | |||
|
1369 | updateSticky() | |||
835 | } |
|
1370 | } | |
836 | .right-sidebar-collapsed-state { |
|
|||
837 | display: flex; |
|
|||
838 | flex-direction: column; |
|
|||
839 | justify-content: center; |
|
|||
840 | align-items: center; |
|
|||
841 | padding: 0 10px; |
|
|||
842 | cursor: pointer; |
|
|||
843 | font-size: 1.3em; |
|
|||
844 | margin: 0 -10px; |
|
|||
845 | } |
|
|||
846 |
|
||||
847 | .right-sidebar-collapsed-state:hover { |
|
|||
848 | background-color: #dbd9da; |
|
|||
849 | } |
|
|||
850 |
|
||||
851 | .navbar__inner { |
|
|||
852 | height: 100%; |
|
|||
853 | background: #fafafa; |
|
|||
854 | position: relative; |
|
|||
855 | } |
|
1371 | } | |
856 |
|
1372 | |||
857 | </style> |
|
1373 | var expandSidebar = function() { | |
858 |
|
||||
859 |
|
||||
860 |
|
||||
861 | <aside class="right-sidebar right-sidebar-expanded"> |
|
|||
862 | <div class="sidenav"> |
|
|||
863 | ## TOGGLE |
|
|||
864 | <div class="sidebar-toggle" onclick="toggleSidebar(); return false"> |
|
|||
865 | <a href="#toggleSidebar"> |
|
|||
866 |
|
||||
867 | </a> |
|
|||
868 | </div> |
|
|||
869 |
|
||||
870 | ## CONTENT |
|
|||
871 | <div class="sidebar-content"> |
|
|||
872 |
|
||||
873 | ## RULES SUMMARY/RULES |
|
|||
874 | <div class="sidebar-element clear-both"> |
|
|||
875 |
|
||||
876 | <div class="tooltip right-sidebar-collapsed-state" style="display: none" onclick="toggleSidebar(); return false" title="${_('Reviewers')}"> |
|
|||
877 | <i class="icon-circle review-status-${c.pull_request_review_status}"></i> |
|
|||
878 | <br/>${len(c.pull_request_reviewers)} |
|
|||
879 | </div> |
|
|||
880 |
|
||||
881 | ## REVIEW RULES |
|
|||
882 | <div id="review_rules" style="display: none" class=""> |
|
|||
883 | <div class="pr-details-title"> |
|
|||
884 | <span class="sidebar-heading"> |
|
|||
885 | ${_('Reviewer rules')} |
|
|||
886 | </span> |
|
|||
887 |
|
||||
888 | </div> |
|
|||
889 | <div class="pr-reviewer-rules"> |
|
|||
890 | ## review rules will be appended here, by default reviewers logic |
|
|||
891 | </div> |
|
|||
892 | <input id="review_data" type="hidden" name="review_data" value=""> |
|
|||
893 | </div> |
|
|||
894 |
|
||||
895 | ## REVIEWERS |
|
|||
896 | <div class="right-sidebar-expanded-state pr-details-title"> |
|
|||
897 | <span class="sidebar-heading"> |
|
|||
898 | <i class="icon-circle review-status-${c.pull_request_review_status}"></i> |
|
|||
899 | ${_('Reviewers')} - ${len(c.pull_request_reviewers)} |
|
|||
900 | </span> |
|
|||
901 | %if c.allowed_to_update: |
|
|||
902 | <span id="open_edit_reviewers" class="block-right action_button last-item">${_('Edit')}</span> |
|
|||
903 | <span id="close_edit_reviewers" class="block-right action_button last-item" style="display: none;">${_('Close')}</span> |
|
|||
904 | %endif |
|
|||
905 | </div> |
|
|||
906 | <div id="reviewers" class="right-sidebar-expanded-state pr-details-content reviewers"> |
|
|||
907 |
|
||||
908 | ## members redering block |
|
|||
909 | <input type="hidden" name="__start__" value="review_members:sequence"> |
|
|||
910 | <ul id="review_members" class="group_members"> |
|
|||
911 |
|
||||
912 | % for review_obj, member, reasons, mandatory, status in c.pull_request_reviewers: |
|
|||
913 | <script> |
|
|||
914 | var member = ${h.json.dumps(h.reviewer_as_json(member, reasons=reasons, mandatory=mandatory, user_group=review_obj.rule_user_group_data()))|n}; |
|
|||
915 | var status = "${(status[0][1].status if status else 'not_reviewed')}"; |
|
|||
916 | var status_lbl = "${h.commit_status_lbl(status[0][1].status if status else 'not_reviewed')}"; |
|
|||
917 | var allowed_to_update = ${h.json.dumps(c.allowed_to_update)}; |
|
|||
918 |
|
||||
919 | var entry = renderTemplate('reviewMemberEntry', { |
|
|||
920 | 'member': member, |
|
|||
921 | 'mandatory': member.mandatory, |
|
|||
922 | 'reasons': member.reasons, |
|
|||
923 | 'allowed_to_update': allowed_to_update, |
|
|||
924 | 'review_status': status, |
|
|||
925 | 'review_status_label': status_lbl, |
|
|||
926 | 'user_group': member.user_group, |
|
|||
927 | 'create': false |
|
|||
928 | }); |
|
|||
929 | $('#review_members').append(entry) |
|
|||
930 | </script> |
|
|||
931 |
|
||||
932 | % endfor |
|
|||
933 |
|
||||
934 | </ul> |
|
|||
935 |
|
||||
936 | <input type="hidden" name="__end__" value="review_members:sequence"> |
|
|||
937 | ## end members redering block |
|
|||
938 |
|
||||
939 | %if not c.pull_request.is_closed(): |
|
|||
940 | <div id="add_reviewer" class="ac" style="display: none;"> |
|
|||
941 | %if c.allowed_to_update: |
|
|||
942 | % if not c.forbid_adding_reviewers: |
|
|||
943 | <div id="add_reviewer_input" class="reviewer_ac"> |
|
|||
944 | ${h.text('user', class_='ac-input', placeholder=_('Add reviewer or reviewer group'))} |
|
|||
945 | <div id="reviewers_container"></div> |
|
|||
946 | </div> |
|
|||
947 | % endif |
|
|||
948 | <div class="pull-right"> |
|
|||
949 | <button id="update_pull_request" class="btn btn-small no-margin">${_('Save Changes')}</button> |
|
|||
950 | </div> |
|
|||
951 | %endif |
|
|||
952 | </div> |
|
|||
953 | %endif |
|
|||
954 | </div> |
|
|||
955 | </div> |
|
|||
956 |
|
||||
957 | ## OBSERVERS |
|
|||
958 | <div class="sidebar-element clear-both"> |
|
|||
959 | <div class="tooltip right-sidebar-collapsed-state" style="display: none" onclick="toggleSidebar(); return false" title="${_('Observers')}"> |
|
|||
960 | <i class="icon-eye"></i> |
|
|||
961 | <br/> 0 |
|
|||
962 | </div> |
|
|||
963 |
|
||||
964 | <div class="right-sidebar-expanded-state pr-details-title"> |
|
|||
965 | <span class="sidebar-heading"> |
|
|||
966 | <i class="icon-eye"></i> |
|
|||
967 | ${_('Observers')} |
|
|||
968 | </span> |
|
|||
969 | </div> |
|
|||
970 | <div class="right-sidebar-expanded-state pr-details-content"> |
|
|||
971 | No observers - 0 |
|
|||
972 | </div> |
|
|||
973 | </div> |
|
|||
974 |
|
||||
975 | ## TODOs |
|
|||
976 | <div class="sidebar-element clear-both"> |
|
|||
977 | <div class="tooltip right-sidebar-collapsed-state" style="display: none" onclick="toggleSidebar(); return false" title="TODOs"> |
|
|||
978 | <i class="icon-flag-filled"></i> |
|
|||
979 | <br/> ${len(c.unresolved_comments)} |
|
|||
980 | </div> |
|
|||
981 |
|
||||
982 | ## TODOs will be listed here |
|
|||
983 | <div class="right-sidebar-expanded-state pr-details-title"> |
|
|||
984 | ## Only show unresolved, that is only what matters |
|
|||
985 | <span class="sidebar-heading"> |
|
|||
986 | <i class="icon-flag-filled"></i> |
|
|||
987 | TODOs - ${len(c.unresolved_comments)} |
|
|||
988 | ##/ ${(len(c.unresolved_comments) + len(c.resolved_comments))} |
|
|||
989 | </span> |
|
|||
990 |
|
||||
991 | % if not c.at_version: |
|
|||
992 | % if c.resolved_comments: |
|
|||
993 | <span class="block-right action_button last-item noselect" onclick="$('.unresolved-todo-text').toggle(); return versionController.toggleElement(this, '.unresolved-todo');" data-toggle-on="Show resolved" data-toggle-off="Hide resolved">Show resolved</span> |
|
|||
994 | % else: |
|
|||
995 | <span class="block-right last-item noselect">Show resolved</span> |
|
|||
996 | % endif |
|
|||
997 | % endif |
|
|||
998 | </div> |
|
|||
999 |
|
||||
1000 | <div class="right-sidebar-expanded-state pr-details-content"> |
|
|||
1001 |
|
||||
1002 | <table class="todo-table"> |
|
|||
1003 | <% |
|
|||
1004 | def sorter(entry): |
|
|||
1005 | user_id = entry.author.user_id |
|
|||
1006 | resolved = '1' if entry.resolved else '0' |
|
|||
1007 | if user_id == c.rhodecode_user.user_id: |
|
|||
1008 | # own comments first |
|
|||
1009 | user_id = 0 |
|
|||
1010 | return '{}_{}_{}'.format(resolved, user_id, str(entry.comment_id).zfill(100)) |
|
|||
1011 | %> |
|
|||
1012 |
|
||||
1013 | % if c.at_version: |
|
|||
1014 | <tr> |
|
|||
1015 | <td class="unresolved-todo-text">${_('unresolved TODOs unavailable in this view')}.</td> |
|
|||
1016 | </tr> |
|
|||
1017 | % else: |
|
|||
1018 | % for todo_comment in sorted(c.unresolved_comments + c.resolved_comments, key=sorter): |
|
|||
1019 | <% resolved = todo_comment.resolved %> |
|
|||
1020 | % if inline: |
|
|||
1021 | <% outdated_at_ver = todo_comment.outdated_at_version(getattr(c, 'at_version_num', None)) %> |
|
|||
1022 | % else: |
|
|||
1023 | <% outdated_at_ver = todo_comment.older_than_version(getattr(c, 'at_version_num', None)) %> |
|
|||
1024 | % endif |
|
|||
1025 |
|
||||
1026 | <tr ${('class="unresolved-todo" style="display: none"' if resolved else '') |n}> |
|
|||
1027 |
|
||||
1028 | <td class="td-todo-number"> |
|
|||
1029 | % if resolved: |
|
|||
1030 | <a class="permalink todo-resolved tooltip" title="${_('Resolved by comment #{}').format(todo_comment.resolved.comment_id)}" href="#comment-${todo_comment.comment_id}" onclick="return Rhodecode.comments.scrollToComment($('#comment-${todo_comment.comment_id}'), 0, ${h.json.dumps(outdated_at_ver)})"> |
|
|||
1031 | <i class="icon-flag-filled"></i> ${todo_comment.comment_id}</a> |
|
|||
1032 | % else: |
|
|||
1033 | <a class="permalink" href="#comment-${todo_comment.comment_id}" onclick="return Rhodecode.comments.scrollToComment($('#comment-${todo_comment.comment_id}'), 0, ${h.json.dumps(outdated_at_ver)})"> |
|
|||
1034 | <i class="icon-flag-filled"></i> ${todo_comment.comment_id}</a> |
|
|||
1035 | % endif |
|
|||
1036 | </td> |
|
|||
1037 | <td class="td-todo-gravatar"> |
|
|||
1038 | ${base.gravatar(todo_comment.author.email, 16, user=todo_comment.author, tooltip=True, extra_class=['no-margin'])} |
|
|||
1039 | </td> |
|
|||
1040 | <td class="todo-comment-text-wrapper"> |
|
|||
1041 | <div class="todo-comment-text"> |
|
|||
1042 | <code>${h.chop_at_smart(todo_comment.text, '\n', suffix_if_chopped='...')}</code> |
|
|||
1043 | </div> |
|
|||
1044 | </td> |
|
|||
1045 |
|
||||
1046 | </tr> |
|
|||
1047 | % endfor |
|
|||
1048 |
|
||||
1049 | % if len(c.unresolved_comments) == 0: |
|
|||
1050 | <tr> |
|
|||
1051 | <td class="unresolved-todo-text">${_('No unresolved TODOs')}.</td> |
|
|||
1052 | </tr> |
|
|||
1053 | % endif |
|
|||
1054 |
|
||||
1055 | % endif |
|
|||
1056 |
|
||||
1057 | </table> |
|
|||
1058 |
|
||||
1059 | </div> |
|
|||
1060 | </div> |
|
|||
1061 |
|
||||
1062 | ## COMMENTS |
|
|||
1063 | <div class="sidebar-element clear-both"> |
|
|||
1064 | <div class="tooltip right-sidebar-collapsed-state" style="display: none" onclick="toggleSidebar(); return false" title="${_('Comments')}"> |
|
|||
1065 | <i class="icon-comment" style="color: #949494"></i> |
|
|||
1066 | <br/> ${len(c.inline_comments_flat+c.comments)} |
|
|||
1067 | </div> |
|
|||
1068 |
|
||||
1069 | <div class="right-sidebar-expanded-state pr-details-title"> |
|
|||
1070 | <span class="sidebar-heading"> |
|
|||
1071 | <i class="icon-comment" style="color: #949494"></i> |
|
|||
1072 | ${_('Comments')} - ${len(c.inline_comments_flat+c.comments)} |
|
|||
1073 | ##${_ungettext("{} General", "{} General", len(c.comments)).format(len(c.comments))} / |
|
|||
1074 | ##${_ungettext("{} Inline", "{} Inline", c.inline_cnt).format(len(c.inline_comments_flat))} |
|
|||
1075 |
|
||||
1076 | ## TODO check why this ins't working |
|
|||
1077 | % if pull_request_menu: |
|
|||
1078 | <% |
|
|||
1079 | outdated_comm_count_ver = pull_request_menu['outdated_comm_count_ver'] |
|
|||
1080 | %> |
|
|||
1081 |
|
||||
1082 | % if outdated_comm_count_ver: |
|
|||
1083 | <a href="#" onclick="showOutdated(); Rhodecode.comments.nextOutdatedComment(); return false;"> |
|
|||
1084 | (${_("{} Outdated").format(outdated_comm_count_ver)}) |
|
|||
1085 | </a> |
|
|||
1086 | <a href="#" class="showOutdatedComments" onclick="showOutdated(this); return false;"> | ${_('show outdated')}</a> |
|
|||
1087 | <a href="#" class="hideOutdatedComments" style="display: none" onclick="hideOutdated(this); return false;"> | ${_('hide outdated')}</a> |
|
|||
1088 | % else: |
|
|||
1089 | (${_("{} Outdated").format(outdated_comm_count_ver)}) |
|
|||
1090 | % endif |
|
|||
1091 |
|
||||
1092 | % endif |
|
|||
1093 | </span> |
|
|||
1094 | <span class="block-right action_button last-item noselect" onclick="return versionController.toggleElement(this, '.hidden-comment');" data-toggle-on="Show all" data-toggle-off="Hide all">Show all</span> |
|
|||
1095 | </div> |
|
|||
1096 |
|
||||
1097 | <div class="right-sidebar-expanded-state pr-details-content"> |
|
|||
1098 | <table class="todo-table"> |
|
|||
1099 | <% |
|
|||
1100 | def sorter(entry): |
|
|||
1101 | user_id = entry.author.user_id |
|
|||
1102 | return '{}'.format(str(entry.comment_id).zfill(100)) |
|
|||
1103 | %> |
|
|||
1104 |
|
||||
1105 | % for comment_obj in reversed(sorted(c.inline_comments_flat + c.comments, key=sorter)): |
|
|||
1106 | <% |
|
|||
1107 | display = '' |
|
|||
1108 | _cls = '' |
|
|||
1109 | %> |
|
|||
1110 | ## SKIP TODOs we display them above |
|
|||
1111 | % if comment_obj.is_todo: |
|
|||
1112 | <% display = 'none' %> |
|
|||
1113 | % endif |
|
|||
1114 |
|
||||
1115 | ## Skip outdated comments |
|
|||
1116 | % if comment_obj.outdated: |
|
|||
1117 | <% display = 'none' %> |
|
|||
1118 | <% _cls = 'hidden-comment' %> |
|
|||
1119 | % endif |
|
|||
1120 |
|
||||
1121 | <tr class="${_cls}" style="display: ${display}"> |
|
|||
1122 | <td class="td-todo-number"> |
|
|||
1123 | <a class="permalink" href="#comment-${comment_obj.comment_id}" onclick="return Rhodecode.comments.scrollToComment($('#comment-${comment_obj.comment_id}'), 0, ${comment_obj.outdated_js})"> |
|
|||
1124 | % if comment_obj.outdated: |
|
|||
1125 | <i class="tooltip icon-comment-toggle" title="Outdated"></i> |
|
|||
1126 | % elif comment_obj.is_inline: |
|
|||
1127 | <i class="tooltip icon-code" title="Inline"></i> |
|
|||
1128 | % else: |
|
|||
1129 | <i class="tooltip icon-comment" title="General"></i> |
|
|||
1130 | % endif |
|
|||
1131 | ${comment_obj.comment_id} |
|
|||
1132 | </a> |
|
|||
1133 | </td> |
|
|||
1134 | <td class="td-todo-gravatar"> |
|
|||
1135 | ${base.gravatar(comment_obj.author.email, 16, user=comment_obj.author, tooltip=True, extra_class=['no-margin'])} |
|
|||
1136 | </td> |
|
|||
1137 | <td class="todo-comment-text-wrapper"> |
|
|||
1138 | <div class="todo-comment-text"> |
|
|||
1139 | <code>${h.chop_at_smart(comment_obj.text, '\n', suffix_if_chopped='...')}</code> |
|
|||
1140 | </div> |
|
|||
1141 | </td> |
|
|||
1142 | </tr> |
|
|||
1143 | % endfor |
|
|||
1144 |
|
||||
1145 | </table> |
|
|||
1146 | </div> |
|
|||
1147 |
|
||||
1148 | </div> |
|
|||
1149 | </div> |
|
|||
1150 |
|
||||
1151 | </div> |
|
|||
1152 | </aside> |
|
|||
1153 |
|
||||
1154 |
|
||||
1155 | <script> |
|
|||
1156 | var $sideBar = $('.right-sidebar'); |
|
1374 | var $sideBar = $('.right-sidebar'); | |
1157 | var marginExpanded = {'margin': '0 320px 0 0'}; |
|
|||
1158 | var marginCollapsed = {'margin': '0 50px 0 0'}; |
|
|||
1159 |
|
||||
1160 | if($sideBar.hasClass('right-sidebar-expanded')) { |
|
|||
1161 | $('.outerwrapper').css(marginExpanded); |
|
1375 | $('.outerwrapper').css(marginExpanded); | |
|
1376 | $('.header').css(marginExpandedHeader); | |||
1162 | $('.sidebar-toggle a').html('<i class="icon-right" style="margin-right: -10px"></i><i class="icon-right"></i>'); |
|
1377 | $('.sidebar-toggle a').html('<i class="icon-right" style="margin-right: -10px"></i><i class="icon-right"></i>'); | |
1163 | $('.right-sidebar-collapsed-state').hide(); |
|
1378 | $('.right-sidebar-collapsed-state').hide(); | |
1164 | $('.right-sidebar-expanded-state').show(); |
|
1379 | $('.right-sidebar-expanded-state').show(); | |
1165 | updateSticky() |
|
|||
1166 |
|
1380 | |||
1167 | } else { |
|
1381 | $sideBar.addClass('right-sidebar-expanded') | |
1168 | $('.outerwrapper').css(marginCollapsed); |
|
1382 | $sideBar.removeClass('right-sidebar-collapsed') | |
1169 | $('.sidebar-toggle a').html('<i class="icon-left" style="margin-right: -10px"></i><i class="icon-left"></i>'); |
|
|||
1170 | $('.right-sidebar-collapsed-state').hide(); |
|
|||
1171 | $('.right-sidebar-expanded-state').show(); |
|
|||
1172 | updateSticky() |
|
|||
1173 | } |
|
1383 | } | |
1174 |
|
1384 | |||
1175 |
var |
|
1385 | var collapseSidebar = function() { | |
1176 | var $sideBar = $('.right-sidebar'); |
|
1386 | var $sideBar = $('.right-sidebar'); | |
1177 |
|
||||
1178 | if($sideBar.hasClass('right-sidebar-expanded')) { |
|
|||
1179 | // collapse now |
|
|||
1180 | $sideBar.removeClass('right-sidebar-expanded') |
|
|||
1181 | $sideBar.addClass('right-sidebar-collapsed') |
|
|||
1182 | $('.outerwrapper').css(marginCollapsed); |
|
1387 | $('.outerwrapper').css(marginCollapsed); | |
|
1388 | $('.header').css(marginCollapsedHeader); | |||
1183 | $('.sidebar-toggle a').html('<i class="icon-left" style="margin-right: -10px"></i><i class="icon-left"></i>'); |
|
1389 | $('.sidebar-toggle a').html('<i class="icon-left" style="margin-right: -10px"></i><i class="icon-left"></i>'); | |
1184 | $('.right-sidebar-collapsed-state').show(); |
|
1390 | $('.right-sidebar-collapsed-state').show(); | |
1185 | $('.right-sidebar-expanded-state').hide(); |
|
1391 | $('.right-sidebar-expanded-state').hide(); | |
1186 |
|
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 | ||||
1187 | } else { |
|
1405 | } else { | |
1188 |
// expand |
|
1406 | // collapsed -> expanded | |
1189 | $('.outerwrapper').css(marginExpanded); |
|
1407 | expandSidebar(); | |
1190 | $sideBar.addClass('right-sidebar-expanded') |
|
1408 | var sidebarState = 'expanded'; | |
1191 | $sideBar.removeClass('right-sidebar-collapsed') |
|
|||
1192 | $('.sidebar-toggle a').html('<i class="icon-right" style="margin-right: -10px"></i><i class="icon-right"></i>'); |
|
|||
1193 | $('.right-sidebar-collapsed-state').hide(); |
|
|||
1194 | $('.right-sidebar-expanded-state').show(); |
|
|||
1195 | } |
|
1409 | } | |
1196 |
|
1410 | |||
1197 | // update our other sticky header in same context |
|
1411 | // update our other sticky header in same context | |
1198 | updateSticky() |
|
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 | |||
1199 | } |
|
1422 | } | |
1200 |
|
1423 | |||
1201 | var sidebarElement = document.getElementById('pr-nav-sticky'); |
|
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(); | |||
1202 |
|
1431 | |||
1203 | ## sidebar = new StickySidebar(sidebarElement, { |
|
1432 | } else { | |
1204 | ## containerSelector: '.main', |
|
1433 | collapseSidebar(); | |
1205 | ## minWidth: 62, |
|
1434 | updateStickyHeader(); | |
1206 | ## innerWrapperSelector: '.navbar__inner', |
|
1435 | } | |
1207 | ## stickyClass: 'is-sticky', |
|
1436 | var channel = '${c.pr_broadcast_channel}'; | |
1208 | ## }); |
|
1437 | new PullRequestPresenceController(channel) | |
1209 |
|
1438 | |||
|
1439 | }) | |||
1210 | </script> |
|
1440 | </script> | |
|
1441 | ||||
1211 | </%def> |
|
1442 | </%def> |
General Comments 0
You need to be logged in to leave comments.
Login now