Show More
@@ -694,8 +694,8 b' def make_map(config):' | |||||
694 | requirements=URL_NAME_REQUIREMENTS, jsroute=True) |
|
694 | requirements=URL_NAME_REQUIREMENTS, jsroute=True) | |
695 |
|
695 | |||
696 | rmap.connect('repo_refs_data', '/{repo_name}/refs-data', |
|
696 | rmap.connect('repo_refs_data', '/{repo_name}/refs-data', | |
697 |
controller='summary', action='repo_refs_data', |
|
697 | controller='summary', action='repo_refs_data', | |
698 | requirements=URL_NAME_REQUIREMENTS) |
|
698 | requirements=URL_NAME_REQUIREMENTS, jsroute=True) | |
699 | rmap.connect('repo_refs_changelog_data', '/{repo_name}/refs-data-changelog', |
|
699 | rmap.connect('repo_refs_changelog_data', '/{repo_name}/refs-data-changelog', | |
700 | controller='summary', action='repo_refs_changelog_data', |
|
700 | controller='summary', action='repo_refs_changelog_data', | |
701 | requirements=URL_NAME_REQUIREMENTS, jsroute=True) |
|
701 | requirements=URL_NAME_REQUIREMENTS, jsroute=True) | |
@@ -704,9 +704,9 b' def make_map(config):' | |||||
704 | jsroute=True, requirements=URL_NAME_REQUIREMENTS) |
|
704 | jsroute=True, requirements=URL_NAME_REQUIREMENTS) | |
705 |
|
705 | |||
706 | rmap.connect('changeset_home', '/{repo_name}/changeset/{revision}', |
|
706 | rmap.connect('changeset_home', '/{repo_name}/changeset/{revision}', | |
707 |
controller='changeset', revision='tip', |
|
707 | controller='changeset', revision='tip', | |
708 | conditions={'function': check_repo}, |
|
708 | conditions={'function': check_repo}, | |
709 | requirements=URL_NAME_REQUIREMENTS) |
|
709 | requirements=URL_NAME_REQUIREMENTS, jsroute=True) | |
710 | rmap.connect('changeset_children', '/{repo_name}/changeset_children/{revision}', |
|
710 | rmap.connect('changeset_children', '/{repo_name}/changeset_children/{revision}', | |
711 | controller='changeset', revision='tip', action='changeset_children', |
|
711 | controller='changeset', revision='tip', action='changeset_children', | |
712 | conditions={'function': check_repo}, |
|
712 | conditions={'function': check_repo}, | |
@@ -923,7 +923,7 b' def make_map(config):' | |||||
923 | controller='pullrequests', |
|
923 | controller='pullrequests', | |
924 | action='show', conditions={'function': check_repo, |
|
924 | action='show', conditions={'function': check_repo, | |
925 | 'method': ['GET']}, |
|
925 | 'method': ['GET']}, | |
926 | requirements=URL_NAME_REQUIREMENTS) |
|
926 | requirements=URL_NAME_REQUIREMENTS, jsroute=True) | |
927 |
|
927 | |||
928 | rmap.connect('pullrequest_update', |
|
928 | rmap.connect('pullrequest_update', | |
929 | '/{repo_name}/pull-request/{pull_request_id}', |
|
929 | '/{repo_name}/pull-request/{pull_request_id}', |
@@ -904,6 +904,8 b' class PullrequestsController(BaseRepoCon' | |||||
904 | status = request.POST.get('changeset_status', None) |
|
904 | status = request.POST.get('changeset_status', None) | |
905 | text = request.POST.get('text') |
|
905 | text = request.POST.get('text') | |
906 | comment_type = request.POST.get('comment_type') |
|
906 | comment_type = request.POST.get('comment_type') | |
|
907 | resolves_comment_id = request.POST.get('resolves_comment_id') | |||
|
908 | ||||
907 | if status and '_closed' in status: |
|
909 | if status and '_closed' in status: | |
908 | close_pr = True |
|
910 | close_pr = True | |
909 | status = status.replace('_closed', '') |
|
911 | status = status.replace('_closed', '') | |
@@ -936,7 +938,8 b' class PullrequestsController(BaseRepoCon' | |||||
936 | status_change_type=(status |
|
938 | status_change_type=(status | |
937 | if status and allowed_to_change_status else None), |
|
939 | if status and allowed_to_change_status else None), | |
938 | closing_pr=close_pr, |
|
940 | closing_pr=close_pr, | |
939 | comment_type=comment_type |
|
941 | comment_type=comment_type, | |
|
942 | resolves_comment_id=resolves_comment_id | |||
940 | ) |
|
943 | ) | |
941 |
|
944 | |||
942 | if allowed_to_change_status: |
|
945 | if allowed_to_change_status: |
@@ -84,9 +84,10 b' class CommentsModel(BaseModel):' | |||||
84 | return global_renderer |
|
84 | return global_renderer | |
85 |
|
85 | |||
86 | def create(self, text, repo, user, commit_id=None, pull_request=None, |
|
86 | def create(self, text, repo, user, commit_id=None, pull_request=None, | |
87 |
f_path=None, line_no=None, status_change=None, |
|
87 | f_path=None, line_no=None, status_change=None, | |
88 |
status_change_type=None, c |
|
88 | status_change_type=None, comment_type=None, | |
89 | send_email=True, renderer=None): |
|
89 | resolves_comment_id=None, closing_pr=False, send_email=True, | |
|
90 | renderer=None): | |||
90 | """ |
|
91 | """ | |
91 | Creates new comment for commit or pull request. |
|
92 | Creates new comment for commit or pull request. | |
92 | IF status_change is not none this comment is associated with a |
|
93 | IF status_change is not none this comment is associated with a | |
@@ -113,6 +114,8 b' class CommentsModel(BaseModel):' | |||||
113 | if not renderer: |
|
114 | if not renderer: | |
114 | renderer = self._get_renderer() |
|
115 | renderer = self._get_renderer() | |
115 |
|
116 | |||
|
117 | repo = self._get_repo(repo) | |||
|
118 | user = self._get_user(user) | |||
116 |
|
119 | |||
117 | schema = comment_schema.CommentSchema() |
|
120 | schema = comment_schema.CommentSchema() | |
118 | validated_kwargs = schema.deserialize(dict( |
|
121 | validated_kwargs = schema.deserialize(dict( | |
@@ -121,15 +124,12 b' class CommentsModel(BaseModel):' | |||||
121 | comment_file=f_path, |
|
124 | comment_file=f_path, | |
122 | comment_line=line_no, |
|
125 | comment_line=line_no, | |
123 | renderer_type=renderer, |
|
126 | renderer_type=renderer, | |
124 | status_change=status_change, |
|
127 | status_change=status_change_type, | |
125 |
|
128 | resolves_comment_id=resolves_comment_id, | ||
126 | repo=repo, |
|
129 | repo=repo.repo_id, | |
127 | user=user, |
|
130 | user=user.user_id, | |
128 | )) |
|
131 | )) | |
129 |
|
132 | |||
130 | repo = self._get_repo(validated_kwargs['repo']) |
|
|||
131 | user = self._get_user(validated_kwargs['user']) |
|
|||
132 |
|
||||
133 | comment = ChangesetComment() |
|
133 | comment = ChangesetComment() | |
134 | comment.renderer = validated_kwargs['renderer_type'] |
|
134 | comment.renderer = validated_kwargs['renderer_type'] | |
135 | comment.text = validated_kwargs['comment_body'] |
|
135 | comment.text = validated_kwargs['comment_body'] | |
@@ -139,6 +139,8 b' class CommentsModel(BaseModel):' | |||||
139 |
|
139 | |||
140 | comment.repo = repo |
|
140 | comment.repo = repo | |
141 | comment.author = user |
|
141 | comment.author = user | |
|
142 | comment.resolved_comment = self.__get_commit_comment( | |||
|
143 | validated_kwargs['resolves_comment_id']) | |||
142 |
|
144 | |||
143 | pull_request_id = pull_request |
|
145 | pull_request_id = pull_request | |
144 |
|
146 |
@@ -2917,7 +2917,7 b' class ChangesetComment(Base, BaseModel):' | |||||
2917 |
|
2917 | |||
2918 | comment_type = Column('comment_type', Unicode(128), nullable=True, default=COMMENT_TYPE_NOTE) |
|
2918 | comment_type = Column('comment_type', Unicode(128), nullable=True, default=COMMENT_TYPE_NOTE) | |
2919 | resolved_comment_id = Column('resolved_comment_id', Integer(), ForeignKey('changeset_comments.comment_id'), nullable=True) |
|
2919 | resolved_comment_id = Column('resolved_comment_id', Integer(), ForeignKey('changeset_comments.comment_id'), nullable=True) | |
2920 | resolved_comment = relationship('ChangesetComment', remote_side=comment_id) |
|
2920 | resolved_comment = relationship('ChangesetComment', remote_side=comment_id, backref='resolved_by') | |
2921 | author = relationship('User', lazy='joined') |
|
2921 | author = relationship('User', lazy='joined') | |
2922 | repo = relationship('Repository') |
|
2922 | repo = relationship('Repository') | |
2923 | status_change = relationship('ChangesetStatus', cascade="all, delete, delete-orphan") |
|
2923 | status_change = relationship('ChangesetStatus', cascade="all, delete, delete-orphan") | |
@@ -2959,6 +2959,10 b' class ChangesetComment(Base, BaseModel):' | |||||
2959 | """ |
|
2959 | """ | |
2960 | return self.outdated and self.pull_request_version_id != version |
|
2960 | return self.outdated and self.pull_request_version_id != version | |
2961 |
|
2961 | |||
|
2962 | @property | |||
|
2963 | def resolved(self): | |||
|
2964 | return self.resolved_by[0] if self.resolved_by else None | |||
|
2965 | ||||
2962 | def get_index_version(self, versions): |
|
2966 | def get_index_version(self, versions): | |
2963 | return self.get_index_from_version( |
|
2967 | return self.get_index_from_version( | |
2964 | self.pull_request_version_id, versions) |
|
2968 | self.pull_request_version_id, versions) |
@@ -53,18 +53,22 b" comment_types = ['note', 'todo']" | |||||
53 |
|
53 | |||
54 |
|
54 | |||
55 | class CommentSchema(colander.MappingSchema): |
|
55 | class CommentSchema(colander.MappingSchema): | |
56 | from rhodecode.model.db import ChangesetComment |
|
56 | from rhodecode.model.db import ChangesetComment, ChangesetStatus | |
57 |
|
57 | |||
58 | comment_body = colander.SchemaNode(colander.String()) |
|
58 | comment_body = colander.SchemaNode(colander.String()) | |
59 | comment_type = colander.SchemaNode( |
|
59 | comment_type = colander.SchemaNode( | |
60 | colander.String(), |
|
60 | colander.String(), | |
61 |
validator=colander.OneOf(ChangesetComment.COMMENT_TYPES) |
|
61 | validator=colander.OneOf(ChangesetComment.COMMENT_TYPES), | |
|
62 | missing=ChangesetComment.COMMENT_TYPE_NOTE) | |||
62 |
|
63 | |||
63 | comment_file = colander.SchemaNode(colander.String(), missing=None) |
|
64 | comment_file = colander.SchemaNode(colander.String(), missing=None) | |
64 | comment_line = colander.SchemaNode(colander.String(), missing=None) |
|
65 | comment_line = colander.SchemaNode(colander.String(), missing=None) | |
65 |
status_change = colander.SchemaNode( |
|
66 | status_change = colander.SchemaNode( | |
|
67 | colander.String(), missing=None, | |||
|
68 | validator=colander.OneOf([x[0] for x in ChangesetStatus.STATUSES])) | |||
66 | renderer_type = colander.SchemaNode(colander.String()) |
|
69 | renderer_type = colander.SchemaNode(colander.String()) | |
67 |
|
70 | |||
68 | # do those ? |
|
71 | resolves_comment_id = colander.SchemaNode(colander.Integer(), missing=None) | |
|
72 | ||||
69 | user = colander.SchemaNode(types.StrOrIntType()) |
|
73 | user = colander.SchemaNode(types.StrOrIntType()) | |
70 | repo = colander.SchemaNode(types.StrOrIntType()) |
|
74 | repo = colander.SchemaNode(types.StrOrIntType()) |
@@ -66,6 +66,7 b' tr.inline-comments div {' | |||||
66 | white-space: nowrap; |
|
66 | white-space: nowrap; | |
67 |
|
67 | |||
68 | text-transform: uppercase; |
|
68 | text-transform: uppercase; | |
|
69 | min-width: 40px; | |||
69 |
|
70 | |||
70 | &.todo { |
|
71 | &.todo { | |
71 | color: @color5; |
|
72 | color: @color5; | |
@@ -366,7 +367,7 b' form.comment-form {' | |||||
366 | display: inline-block; |
|
367 | display: inline-block; | |
367 | } |
|
368 | } | |
368 |
|
369 | |||
369 |
|
|
370 | .comment-button-input { | |
370 | margin-right: 0; |
|
371 | margin-right: 0; | |
371 | } |
|
372 | } | |
372 |
|
373 |
@@ -37,6 +37,7 b' function registerRCRoutes() {' | |||||
37 | pyroutes.register('pullrequest', '/%(repo_name)s/pull-request/new', ['repo_name']); |
|
37 | pyroutes.register('pullrequest', '/%(repo_name)s/pull-request/new', ['repo_name']); | |
38 | pyroutes.register('pullrequest_repo_refs', '/%(repo_name)s/pull-request/refs/%(target_repo_name)s', ['repo_name', 'target_repo_name']); |
|
38 | pyroutes.register('pullrequest_repo_refs', '/%(repo_name)s/pull-request/refs/%(target_repo_name)s', ['repo_name', 'target_repo_name']); | |
39 | pyroutes.register('pullrequest_repo_destinations', '/%(repo_name)s/pull-request/repo-destinations', ['repo_name']); |
|
39 | pyroutes.register('pullrequest_repo_destinations', '/%(repo_name)s/pull-request/repo-destinations', ['repo_name']); | |
|
40 | pyroutes.register('pullrequest_show', '/%(repo_name)s/pull-request/%(pull_request_id)s', ['repo_name', 'pull_request_id']); | |||
40 | pyroutes.register('pullrequest_update', '/%(repo_name)s/pull-request/%(pull_request_id)s', ['repo_name', 'pull_request_id']); |
|
41 | pyroutes.register('pullrequest_update', '/%(repo_name)s/pull-request/%(pull_request_id)s', ['repo_name', 'pull_request_id']); | |
41 | pyroutes.register('pullrequest_show_all', '/%(repo_name)s/pull-request', ['repo_name']); |
|
42 | pyroutes.register('pullrequest_show_all', '/%(repo_name)s/pull-request', ['repo_name']); | |
42 | pyroutes.register('pullrequest_comment', '/%(repo_name)s/pull-request-comment/%(pull_request_id)s', ['repo_name', 'pull_request_id']); |
|
43 | pyroutes.register('pullrequest_comment', '/%(repo_name)s/pull-request-comment/%(pull_request_id)s', ['repo_name', 'pull_request_id']); |
@@ -79,7 +79,7 b' var bindToggleButtons = function() {' | |||||
79 | }; |
|
79 | }; | |
80 |
|
80 | |||
81 | var linkifyComments = function(comments) { |
|
81 | var linkifyComments = function(comments) { | |
82 |
/* TODO: |
|
82 | /* TODO: marcink: remove this - it should no longer needed */ | |
83 | for (var i = 0; i < comments.length; i++) { |
|
83 | for (var i = 0; i < comments.length; i++) { | |
84 | var comment_id = $(comments[i]).data('comment-id'); |
|
84 | var comment_id = $(comments[i]).data('comment-id'); | |
85 | var prev_comment_id = $(comments[i - 1]).data('comment-id'); |
|
85 | var prev_comment_id = $(comments[i - 1]).data('comment-id'); | |
@@ -96,6 +96,8 b' var linkifyComments = function(comments)' | |||||
96 | $('#next_c_' + comment_id + " a.arrow_comment_link").attr( |
|
96 | $('#next_c_' + comment_id + " a.arrow_comment_link").attr( | |
97 | 'href', '#comment-' + next_comment_id).removeClass('disabled'); |
|
97 | 'href', '#comment-' + next_comment_id).removeClass('disabled'); | |
98 | } |
|
98 | } | |
|
99 | /* TODO(marcink): end removal here */ | |||
|
100 | ||||
99 | // place a first link to the total counter |
|
101 | // place a first link to the total counter | |
100 | if (i === 0) { |
|
102 | if (i === 0) { | |
101 | $('#inline-comments-counter').attr('href', '#comment-' + comment_id); |
|
103 | $('#inline-comments-counter').attr('href', '#comment-' + comment_id); | |
@@ -106,10 +108,23 b' var linkifyComments = function(comments)' | |||||
106 |
|
108 | |||
107 |
|
109 | |||
108 | /* Comment form for main and inline comments */ |
|
110 | /* Comment form for main and inline comments */ | |
109 | var CommentForm = (function() { |
|
111 | ||
|
112 | (function(mod) { | |||
|
113 | if (typeof exports == "object" && typeof module == "object") // CommonJS | |||
|
114 | module.exports = mod(); | |||
|
115 | else // Plain browser env | |||
|
116 | (this || window).CommentForm = mod(); | |||
|
117 | ||||
|
118 | })(function() { | |||
110 | "use strict"; |
|
119 | "use strict"; | |
111 |
|
120 | |||
112 | function CommentForm(formElement, commitId, pullRequestId, lineNo, initAutocompleteActions) { |
|
121 | function CommentForm(formElement, commitId, pullRequestId, lineNo, initAutocompleteActions, resolvesCommentId) { | |
|
122 | if (!(this instanceof CommentForm)) { | |||
|
123 | return new CommentForm(formElement, commitId, pullRequestId, lineNo, initAutocompleteActions, resolvesCommentId); | |||
|
124 | } | |||
|
125 | ||||
|
126 | // bind the element instance to our Form | |||
|
127 | $(formElement).get(0).CommentForm = this; | |||
113 |
|
128 | |||
114 | this.withLineNo = function(selector) { |
|
129 | this.withLineNo = function(selector) { | |
115 | var lineNo = this.lineNo; |
|
130 | var lineNo = this.lineNo; | |
@@ -135,6 +150,9 b' var CommentForm = (function() {' | |||||
135 | this.cancelButton = this.withLineNo('#cancel-btn'); |
|
150 | this.cancelButton = this.withLineNo('#cancel-btn'); | |
136 | this.commentType = this.withLineNo('#comment_type'); |
|
151 | this.commentType = this.withLineNo('#comment_type'); | |
137 |
|
152 | |||
|
153 | this.resolvesId = null; | |||
|
154 | this.resolvesActionId = null; | |||
|
155 | ||||
138 | this.cmBox = this.withLineNo('#text'); |
|
156 | this.cmBox = this.withLineNo('#text'); | |
139 | this.cm = initCommentBoxCodeMirror(this.cmBox, this.initAutocompleteActions); |
|
157 | this.cm = initCommentBoxCodeMirror(this.cmBox, this.initAutocompleteActions); | |
140 |
|
158 | |||
@@ -147,17 +165,38 b' var CommentForm = (function() {' | |||||
147 | this.previewUrl = pyroutes.url('changeset_comment_preview', |
|
165 | this.previewUrl = pyroutes.url('changeset_comment_preview', | |
148 | {'repo_name': templateContext.repo_name}); |
|
166 | {'repo_name': templateContext.repo_name}); | |
149 |
|
167 | |||
150 | // based on commitId, or pullReuqestId decide where do we submit |
|
168 | if (resolvesCommentId){ | |
|
169 | this.resolvesId = '#resolve_comment_{0}'.format(resolvesCommentId); | |||
|
170 | this.resolvesActionId = '#resolve_comment_action_{0}'.format(resolvesCommentId); | |||
|
171 | $(this.commentType).prop('disabled', true); | |||
|
172 | $(this.commentType).addClass('disabled'); | |||
|
173 | ||||
|
174 | var resolvedInfo = ( | |||
|
175 | '<li class="">' + | |||
|
176 | '<input type="hidden" id="resolve_comment_{0}" name="resolve_comment_{0}" value="{0}">' + | |||
|
177 | '<button id="resolve_comment_action_{0}" class="resolve-text btn btn-sm" onclick="return Rhodecode.comments.submitResolution({0})">{1} #{0}</button>' + | |||
|
178 | '</li>' | |||
|
179 | ).format(resolvesCommentId, _gettext('resolve comment')); | |||
|
180 | $(resolvedInfo).insertAfter($(this.commentType).parent()); | |||
|
181 | } | |||
|
182 | ||||
|
183 | // based on commitId, or pullRequestId decide where do we submit | |||
151 | // out data |
|
184 | // out data | |
152 | if (this.commitId){ |
|
185 | if (this.commitId){ | |
153 | this.submitUrl = pyroutes.url('changeset_comment', |
|
186 | this.submitUrl = pyroutes.url('changeset_comment', | |
154 | {'repo_name': templateContext.repo_name, |
|
187 | {'repo_name': templateContext.repo_name, | |
155 | 'revision': this.commitId}); |
|
188 | 'revision': this.commitId}); | |
|
189 | this.selfUrl = pyroutes.url('changeset_home', | |||
|
190 | {'repo_name': templateContext.repo_name, | |||
|
191 | 'revision': this.commitId}); | |||
156 |
|
192 | |||
157 | } else if (this.pullRequestId) { |
|
193 | } else if (this.pullRequestId) { | |
158 | this.submitUrl = pyroutes.url('pullrequest_comment', |
|
194 | this.submitUrl = pyroutes.url('pullrequest_comment', | |
159 | {'repo_name': templateContext.repo_name, |
|
195 | {'repo_name': templateContext.repo_name, | |
160 | 'pull_request_id': this.pullRequestId}); |
|
196 | 'pull_request_id': this.pullRequestId}); | |
|
197 | this.selfUrl = pyroutes.url('pullrequest_show', | |||
|
198 | {'repo_name': templateContext.repo_name, | |||
|
199 | 'pull_request_id': this.pullRequestId}); | |||
161 |
|
200 | |||
162 | } else { |
|
201 | } else { | |
163 | throw new Error( |
|
202 | throw new Error( | |
@@ -168,6 +207,13 b' var CommentForm = (function() {' | |||||
168 | return this.cm |
|
207 | return this.cm | |
169 | }; |
|
208 | }; | |
170 |
|
209 | |||
|
210 | this.setPlaceholder = function(placeholder) { | |||
|
211 | var cm = this.getCmInstance(); | |||
|
212 | if (cm){ | |||
|
213 | cm.setOption('placeholder', placeholder); | |||
|
214 | } | |||
|
215 | }; | |||
|
216 | ||||
171 | var self = this; |
|
217 | var self = this; | |
172 |
|
218 | |||
173 | this.getCommentStatus = function() { |
|
219 | this.getCommentStatus = function() { | |
@@ -176,6 +222,15 b' var CommentForm = (function() {' | |||||
176 | this.getCommentType = function() { |
|
222 | this.getCommentType = function() { | |
177 | return $(this.submitForm).find(this.commentType).val(); |
|
223 | return $(this.submitForm).find(this.commentType).val(); | |
178 | }; |
|
224 | }; | |
|
225 | ||||
|
226 | this.getResolvesId = function() { | |||
|
227 | return $(this.submitForm).find(this.resolvesId).val() || null; | |||
|
228 | }; | |||
|
229 | this.markCommentResolved = function(resolvedCommentId){ | |||
|
230 | $('#comment-label-{0}'.format(resolvedCommentId)).find('.resolved').show(); | |||
|
231 | $('#comment-label-{0}'.format(resolvedCommentId)).find('.resolve').hide(); | |||
|
232 | }; | |||
|
233 | ||||
179 | this.isAllowedToSubmit = function() { |
|
234 | this.isAllowedToSubmit = function() { | |
180 | return !$(this.submitButton).prop('disabled'); |
|
235 | return !$(this.submitButton).prop('disabled'); | |
181 | }; |
|
236 | }; | |
@@ -205,12 +260,12 b' var CommentForm = (function() {' | |||||
205 | }); |
|
260 | }); | |
206 | $(this.submitForm).find(this.statusChange).on('change', function() { |
|
261 | $(this.submitForm).find(this.statusChange).on('change', function() { | |
207 | var status = self.getCommentStatus(); |
|
262 | var status = self.getCommentStatus(); | |
208 |
if (status && |
|
263 | if (status && self.lineNo == 'general') { | |
209 | $(self.submitButton).prop('disabled', false); |
|
264 | $(self.submitButton).prop('disabled', false); | |
210 | } |
|
265 | } | |
211 | //todo, fix this name |
|
266 | ||
212 | var placeholderText = _gettext('Comment text will be set automatically based on currently selected status ({0}) ...').format(status); |
|
267 | var placeholderText = _gettext('Comment text will be set automatically based on currently selected status ({0}) ...').format(status); | |
213 |
self. |
|
268 | self.setPlaceholder(placeholderText) | |
214 | }) |
|
269 | }) | |
215 | }; |
|
270 | }; | |
216 |
|
271 | |||
@@ -260,6 +315,7 b' var CommentForm = (function() {' | |||||
260 | var text = self.cm.getValue(); |
|
315 | var text = self.cm.getValue(); | |
261 | var status = self.getCommentStatus(); |
|
316 | var status = self.getCommentStatus(); | |
262 | var commentType = self.getCommentType(); |
|
317 | var commentType = self.getCommentType(); | |
|
318 | var resolvesCommentId = self.getResolvesId(); | |||
263 |
|
319 | |||
264 | if (text === "" && !status) { |
|
320 | if (text === "" && !status) { | |
265 | return; |
|
321 | return; | |
@@ -275,7 +331,9 b' var CommentForm = (function() {' | |||||
275 | 'comment_type': commentType, |
|
331 | 'comment_type': commentType, | |
276 | 'csrf_token': CSRF_TOKEN |
|
332 | 'csrf_token': CSRF_TOKEN | |
277 | }; |
|
333 | }; | |
278 |
|
334 | if (resolvesCommentId){ | ||
|
335 | postData['resolves_comment_id'] = resolvesCommentId; | |||
|
336 | } | |||
279 | var submitSuccessCallback = function(o) { |
|
337 | var submitSuccessCallback = function(o) { | |
280 | if (status) { |
|
338 | if (status) { | |
281 | location.reload(true); |
|
339 | location.reload(true); | |
@@ -284,10 +342,15 b' var CommentForm = (function() {' | |||||
284 | self.resetCommentFormState(); |
|
342 | self.resetCommentFormState(); | |
285 | bindDeleteCommentButtons(); |
|
343 | bindDeleteCommentButtons(); | |
286 | timeagoActivate(); |
|
344 | timeagoActivate(); | |
|
345 | ||||
|
346 | //mark visually which comment was resolved | |||
|
347 | if (resolvesCommentId) { | |||
|
348 | this.markCommentResolved(resolvesCommentId); | |||
|
349 | } | |||
287 | } |
|
350 | } | |
288 | }; |
|
351 | }; | |
289 | var submitFailCallback = function(){ |
|
352 | var submitFailCallback = function(){ | |
290 | self.resetCommentFormState(text) |
|
353 | self.resetCommentFormState(text); | |
291 | }; |
|
354 | }; | |
292 | self.submitAjaxPOST( |
|
355 | self.submitAjaxPOST( | |
293 | self.submitUrl, postData, submitSuccessCallback, submitFailCallback); |
|
356 | self.submitUrl, postData, submitSuccessCallback, submitFailCallback); | |
@@ -367,7 +430,7 b' var CommentForm = (function() {' | |||||
367 |
|
430 | |||
368 | var postData = { |
|
431 | var postData = { | |
369 | 'text': text, |
|
432 | 'text': text, | |
370 | 'renderer': DEFAULT_RENDERER, |
|
433 | 'renderer': templateContext.visual.default_renderer, | |
371 | 'csrf_token': CSRF_TOKEN |
|
434 | 'csrf_token': CSRF_TOKEN | |
372 | }; |
|
435 | }; | |
373 |
|
436 | |||
@@ -404,15 +467,17 b' var CommentForm = (function() {' | |||||
404 | } |
|
467 | } | |
405 |
|
468 | |||
406 | return CommentForm; |
|
469 | return CommentForm; | |
407 |
}) |
|
470 | }); | |
408 |
|
471 | |||
409 | var CommentsController = function() { /* comments controller */ |
|
472 | /* comments controller */ | |
|
473 | var CommentsController = function() { | |||
|
474 | var mainComment = '#text'; | |||
410 | var self = this; |
|
475 | var self = this; | |
411 |
|
476 | |||
412 | this.cancelComment = function(node) { |
|
477 | this.cancelComment = function(node) { | |
413 | var $node = $(node); |
|
478 | var $node = $(node); | |
414 | var $td = $node.closest('td'); |
|
479 | var $td = $node.closest('td'); | |
415 |
$node.closest('.comment-inline-form').remove |
|
480 | $node.closest('.comment-inline-form').remove(); | |
416 | return false; |
|
481 | return false; | |
417 | }; |
|
482 | }; | |
418 |
|
483 | |||
@@ -530,7 +595,8 b' var CommentsController = function() { /*' | |||||
530 | $node.closest('tr').toggleClass('hide-line-comments'); |
|
595 | $node.closest('tr').toggleClass('hide-line-comments'); | |
531 | }; |
|
596 | }; | |
532 |
|
597 | |||
533 | this.createComment = function(node) { |
|
598 | this.createComment = function(node, resolutionComment) { | |
|
599 | var resolvesCommentId = resolutionComment || null; | |||
534 | var $node = $(node); |
|
600 | var $node = $(node); | |
535 | var $td = $node.closest('td'); |
|
601 | var $td = $node.closest('td'); | |
536 | var $form = $td.find('.comment-inline-form'); |
|
602 | var $form = $td.find('.comment-inline-form'); | |
@@ -556,14 +622,16 b' var CommentsController = function() { /*' | |||||
556 |
|
622 | |||
557 | var pullRequestId = templateContext.pull_request_data.pull_request_id; |
|
623 | var pullRequestId = templateContext.pull_request_data.pull_request_id; | |
558 | var commitId = templateContext.commit_data.commit_id; |
|
624 | var commitId = templateContext.commit_data.commit_id; | |
559 | var _form = $form[0]; |
|
625 | var _form = $($form[0]).find('form'); | |
560 | var commentForm = new CommentForm(_form, commitId, pullRequestId, lineno, false); |
|
626 | ||
|
627 | var commentForm = new CommentForm(_form, commitId, pullRequestId, lineno, false, resolvesCommentId); | |||
561 | var cm = commentForm.getCmInstance(); |
|
628 | var cm = commentForm.getCmInstance(); | |
562 |
|
629 | |||
563 | // set a CUSTOM submit handler for inline comments. |
|
630 | // set a CUSTOM submit handler for inline comments. | |
564 | commentForm.setHandleFormSubmit(function(o) { |
|
631 | commentForm.setHandleFormSubmit(function(o) { | |
565 | var text = commentForm.cm.getValue(); |
|
632 | var text = commentForm.cm.getValue(); | |
566 | var commentType = commentForm.getCommentType(); |
|
633 | var commentType = commentForm.getCommentType(); | |
|
634 | var resolvesCommentId = commentForm.getResolvesId(); | |||
567 |
|
635 | |||
568 | if (text === "") { |
|
636 | if (text === "") { | |
569 | return; |
|
637 | return; | |
@@ -589,6 +657,10 b' var CommentsController = function() { /*' | |||||
589 | 'comment_type': commentType, |
|
657 | 'comment_type': commentType, | |
590 | 'csrf_token': CSRF_TOKEN |
|
658 | 'csrf_token': CSRF_TOKEN | |
591 | }; |
|
659 | }; | |
|
660 | if (resolvesCommentId){ | |||
|
661 | postData['resolves_comment_id'] = resolvesCommentId; | |||
|
662 | } | |||
|
663 | ||||
592 | var submitSuccessCallback = function(json_data) { |
|
664 | var submitSuccessCallback = function(json_data) { | |
593 | $form.remove(); |
|
665 | $form.remove(); | |
594 | try { |
|
666 | try { | |
@@ -598,6 +670,11 b' var CommentsController = function() { /*' | |||||
598 |
|
670 | |||
599 | $comments.find('.cb-comment-add-button').before(html); |
|
671 | $comments.find('.cb-comment-add-button').before(html); | |
600 |
|
672 | |||
|
673 | //mark visually which comment was resolved | |||
|
674 | if (resolvesCommentId) { | |||
|
675 | commentForm.markCommentResolved(resolvesCommentId); | |||
|
676 | } | |||
|
677 | ||||
601 | } catch (e) { |
|
678 | } catch (e) { | |
602 | console.error(e); |
|
679 | console.error(e); | |
603 | } |
|
680 | } | |
@@ -616,26 +693,81 b' var CommentsController = function() { /*' | |||||
616 | commentForm.submitUrl, postData, submitSuccessCallback, submitFailCallback); |
|
693 | commentForm.submitUrl, postData, submitSuccessCallback, submitFailCallback); | |
617 | }); |
|
694 | }); | |
618 |
|
695 | |||
|
696 | if (resolvesCommentId){ | |||
|
697 | var placeholderText = _gettext('Leave a comment, or click resolve button to resolve TODO comment #{0}').format(resolvesCommentId); | |||
|
698 | ||||
|
699 | } else { | |||
|
700 | var placeholderText = _gettext('Leave a comment on line {0}.').format(lineno); | |||
|
701 | } | |||
|
702 | ||||
619 | setTimeout(function() { |
|
703 | setTimeout(function() { | |
620 | // callbacks |
|
704 | // callbacks | |
621 | if (cm !== undefined) { |
|
705 | if (cm !== undefined) { | |
622 | cm.setOption('placeholder', _gettext('Leave a comment on line {0}.').format(lineno)); |
|
706 | commentForm.setPlaceholder(placeholderText); | |
623 | cm.focus(); |
|
707 | cm.focus(); | |
624 | cm.refresh(); |
|
708 | cm.refresh(); | |
625 | } |
|
709 | } | |
626 | }, 10); |
|
710 | }, 10); | |
627 |
|
711 | |||
628 |
|
|
712 | $.Topic('/ui/plugins/code/comment_form_built').prepareOrPublish({ | |
629 |
|
|
713 | form: _form, | |
630 |
|
|
714 | parent: $td[0], | |
631 |
|
|
715 | lineno: lineno, | |
632 |
|
|
716 | f_path: f_path} | |
633 |
|
|
717 | ); | |
|
718 | ||||
|
719 | // trigger hash | |||
|
720 | if (resolvesCommentId){ | |||
|
721 | var resolveAction = $(commentForm.resolvesActionId); | |||
|
722 | setTimeout(function() { | |||
|
723 | $('body, html').animate({ scrollTop: resolveAction.offset().top }, 10); | |||
|
724 | }, 100); | |||
|
725 | } | |||
634 | } |
|
726 | } | |
635 |
|
727 | |||
636 | $form.addClass('comment-inline-form-open'); |
|
728 | $form.addClass('comment-inline-form-open'); | |
637 | }; |
|
729 | }; | |
638 |
|
730 | |||
|
731 | this.createResolutionComment = function(commentId){ | |||
|
732 | // hide the trigger text | |||
|
733 | $('#resolve-comment-{0}'.format(commentId)).hide(); | |||
|
734 | ||||
|
735 | var comment = $('#comment-'+commentId); | |||
|
736 | var commentData = comment.data(); | |||
|
737 | ||||
|
738 | if (commentData.commentInline) { | |||
|
739 | var resolutionComment = true; | |||
|
740 | this.createComment(comment, commentId) | |||
|
741 | } else { | |||
|
742 | ||||
|
743 | this.createComment(comment, commentId) | |||
|
744 | ||||
|
745 | console.log('TODO') | |||
|
746 | console.log(commentId) | |||
|
747 | } | |||
|
748 | ||||
|
749 | return false; | |||
|
750 | }; | |||
|
751 | ||||
|
752 | this.submitResolution = function(commentId){ | |||
|
753 | var form = $('#resolve_comment_{0}'.format(commentId)).closest('form'); | |||
|
754 | var commentForm = form.get(0).CommentForm; | |||
|
755 | ||||
|
756 | var cm = commentForm.getCmInstance(); | |||
|
757 | var renderer = templateContext.visual.default_renderer; | |||
|
758 | if (renderer == 'rst'){ | |||
|
759 | var commentUrl = '`#{0} <{1}#comment-{0}>`_'.format(commentId, commentForm.selfUrl); | |||
|
760 | } else if (renderer == 'markdown') { | |||
|
761 | var commentUrl = '[#{0}]({1}#comment-{0})'.format(commentId, commentForm.selfUrl); | |||
|
762 | } else { | |||
|
763 | var commentUrl = '{1}#comment-{0}'.format(commentId, commentForm.selfUrl); | |||
|
764 | } | |||
|
765 | ||||
|
766 | cm.setValue(_gettext('TODO from comment {0} was fixed.').format(commentUrl)); | |||
|
767 | form.submit(); | |||
|
768 | return false; | |||
|
769 | }; | |||
|
770 | ||||
639 | this.renderInlineComments = function(file_comments) { |
|
771 | this.renderInlineComments = function(file_comments) { | |
640 | show_add_button = typeof show_add_button !== 'undefined' ? show_add_button : true; |
|
772 | show_add_button = typeof show_add_button !== 'undefined' ? show_add_button : true; | |
641 |
|
773 |
@@ -15,12 +15,33 b'' | |||||
15 | id="comment-${comment.comment_id}" |
|
15 | id="comment-${comment.comment_id}" | |
16 | line="${comment.line_no}" |
|
16 | line="${comment.line_no}" | |
17 | data-comment-id="${comment.comment_id}" |
|
17 | data-comment-id="${comment.comment_id}" | |
|
18 | data-comment-type="${comment.comment_type}" | |||
|
19 | data-comment-inline=${h.json.dumps(inline)} | |||
18 | style="${'display: none;' if outdated_at_ver else ''}"> |
|
20 | style="${'display: none;' if outdated_at_ver else ''}"> | |
19 |
|
21 | |||
20 | <div class="meta"> |
|
22 | <div class="meta"> | |
21 |
<div class="comment-type-label |
|
23 | <div class="comment-type-label"> | |
22 | <div class="comment-label ${comment.comment_type or 'note'}"> |
|
24 | <div class="comment-label ${comment.comment_type or 'note'}" id="comment-label-${comment.comment_id}"> | |
23 |
|
|
25 | % if comment.comment_type == 'todo': | |
|
26 | % if comment.resolved: | |||
|
27 | <div class="resolved tooltip" title="${_('Resolved by comment #{}').format(comment.resolved.comment_id)}"> | |||
|
28 | <a href="#comment-${comment.resolved.comment_id}">${comment.comment_type}</a> | |||
|
29 | </div> | |||
|
30 | % else: | |||
|
31 | <div class="resolved tooltip" style="display: none"> | |||
|
32 | <span>${comment.comment_type}</span> | |||
|
33 | </div> | |||
|
34 | <div class="resolve tooltip" onclick="return Rhodecode.comments.createResolutionComment(${comment.comment_id});" title="${_('Click to resolve this comment')}"> | |||
|
35 | ${comment.comment_type} | |||
|
36 | </div> | |||
|
37 | % endif | |||
|
38 | % else: | |||
|
39 | % if comment.resolved_comment: | |||
|
40 | fix | |||
|
41 | % else: | |||
|
42 | ${comment.comment_type or 'note'} | |||
|
43 | % endif | |||
|
44 | % endif | |||
24 | </div> |
|
45 | </div> | |
25 | </div> |
|
46 | </div> | |
26 |
|
47 | |||
@@ -120,6 +141,7 b'' | |||||
120 |
|
141 | |||
121 | </div> |
|
142 | </div> | |
122 | </%def> |
|
143 | </%def> | |
|
144 | ||||
123 | ## generate main comments |
|
145 | ## generate main comments | |
124 | <%def name="generate_comments(include_pull_request=False, is_pull_request=False)"> |
|
146 | <%def name="generate_comments(include_pull_request=False, is_pull_request=False)"> | |
125 | <div id="comments"> |
|
147 | <div id="comments"> | |
@@ -137,16 +159,10 b'' | |||||
137 | </div> |
|
159 | </div> | |
138 | </%def> |
|
160 | </%def> | |
139 |
|
161 | |||
140 | ## MAIN COMMENT FORM |
|
162 | ||
141 | <%def name="comments(post_url, cur_status, is_pull_request=False, is_compare=False, change_status=True, form_extras=None)"> |
|
163 | <%def name="comments(post_url, cur_status, is_pull_request=False, is_compare=False, change_status=True, form_extras=None)"> | |
142 |
|
164 | |||
143 | %if is_compare: |
|
165 | ## merge status, and merge action | |
144 | <% form_id = "comments_form_compare" %> |
|
|||
145 | %else: |
|
|||
146 | <% form_id = "comments_form" %> |
|
|||
147 | %endif |
|
|||
148 |
|
||||
149 |
|
||||
150 | %if is_pull_request: |
|
166 | %if is_pull_request: | |
151 | <div class="pull-request-merge"> |
|
167 | <div class="pull-request-merge"> | |
152 | %if c.allowed_to_merge: |
|
168 | %if c.allowed_to_merge: | |
@@ -168,6 +184,7 b'' | |||||
168 | %endif |
|
184 | %endif | |
169 | </div> |
|
185 | </div> | |
170 | %endif |
|
186 | %endif | |
|
187 | ||||
171 | <div class="comments"> |
|
188 | <div class="comments"> | |
172 | <% |
|
189 | <% | |
173 | if is_pull_request: |
|
190 | if is_pull_request: | |
@@ -177,78 +194,28 b'' | |||||
177 | else: |
|
194 | else: | |
178 | placeholder = _('Leave a comment on this Commit.') |
|
195 | placeholder = _('Leave a comment on this Commit.') | |
179 | %> |
|
196 | %> | |
|
197 | ||||
180 | % if c.rhodecode_user.username != h.DEFAULT_USER: |
|
198 | % if c.rhodecode_user.username != h.DEFAULT_USER: | |
181 | <div class="comment-form ac"> |
|
199 | <div class="comment-form ac"> | |
182 | ${h.secure_form(post_url, id_=form_id)} |
|
200 | ## inject form here | |
183 | <div class="comment-area"> |
|
201 | ${comment_form(form_type='general', form_id='general_comment', lineno_id='general', review_statuses=c.commit_statuses, form_extras=form_extras)} | |
184 | <div class="comment-area-header"> |
|
202 | </div> | |
185 | <ul class="nav-links clearfix"> |
|
203 | <script type="text/javascript"> | |
186 | <li class="active"> |
|
204 | // init active elements of commentForm | |
187 | <a href="#edit-btn" tabindex="-1" id="edit-btn">${_('Write')}</a> |
|
205 | var commitId = templateContext.commit_data.commit_id; | |
188 | </li> |
|
206 | var pullRequestId = templateContext.pull_request_data.pull_request_id; | |
189 | <li class=""> |
|
207 | var lineNo = 'general'; | |
190 | <a href="#preview-btn" tabindex="-1" id="preview-btn">${_('Preview')}</a> |
|
208 | var resolvesCommitId = null; | |
191 | </li> |
|
|||
192 | <li class="pull-right"> |
|
|||
193 | <select class="comment-type" id="comment_type" name="comment_type"> |
|
|||
194 | % for val in c.visual.comment_types: |
|
|||
195 | <option value="${val}">${val.upper()}</option> |
|
|||
196 | % endfor |
|
|||
197 | </select> |
|
|||
198 | </li> |
|
|||
199 | </ul> |
|
|||
200 | </div> |
|
|||
201 |
|
||||
202 | <div class="comment-area-write" style="display: block;"> |
|
|||
203 | <div id="edit-container"> |
|
|||
204 | <textarea id="text" name="text" class="comment-block-ta ac-input"></textarea> |
|
|||
205 | </div> |
|
|||
206 | <div id="preview-container" class="clearfix" style="display: none;"> |
|
|||
207 | <div id="preview-box" class="preview-box"></div> |
|
|||
208 | </div> |
|
|||
209 | </div> |
|
|||
210 |
|
209 | |||
211 | <div class="comment-area-footer"> |
|
210 | var mainCommentForm = new CommentForm( | |
212 | <div class="toolbar"> |
|
211 | "#general_comment", commitId, pullRequestId, lineNo, true, resolvesCommitId); | |
213 | <div class="toolbar-text"> |
|
212 | mainCommentForm.setPlaceholder("${placeholder}"); | |
214 | ${(_('Comments parsed using %s syntax with %s support.') % ( |
|
213 | mainCommentForm.initStatusChangeSelector(); | |
215 | ('<a href="%s">%s</a>' % (h.url('%s_help' % c.visual.default_renderer), c.visual.default_renderer.upper())), |
|
214 | </script> | |
216 | ('<span class="tooltip" title="%s">@mention</span>' % _('Use @username inside this text to send notification to this RhodeCode user')) |
|
|||
217 | ) |
|
|||
218 | )|n} |
|
|||
219 | </div> |
|
|||
220 | </div> |
|
|||
221 | </div> |
|
|||
222 | </div> |
|
|||
223 |
|
215 | |||
224 | <div id="comment_form_extras"> |
|
216 | ||
225 | %if form_extras and isinstance(form_extras, (list, tuple)): |
|
|||
226 | % for form_ex_el in form_extras: |
|
|||
227 | ${form_ex_el|n} |
|
|||
228 | % endfor |
|
|||
229 | %endif |
|
|||
230 | </div> |
|
|||
231 | <div class="comment-footer"> |
|
|||
232 | %if change_status: |
|
|||
233 | <div class="status_box"> |
|
|||
234 | <select id="change_status" name="changeset_status"> |
|
|||
235 | <option></option> # Placeholder |
|
|||
236 | %for status,lbl in c.commit_statuses: |
|
|||
237 | <option value="${status}" data-status="${status}">${lbl}</option> |
|
|||
238 | %if is_pull_request and change_status and status in ('approved', 'rejected'): |
|
|||
239 | <option value="${status}_closed" data-status="${status}">${lbl} & ${_('Closed')}</option> |
|
|||
240 | %endif |
|
|||
241 | %endfor |
|
|||
242 | </select> |
|
|||
243 | </div> |
|
|||
244 | %endif |
|
|||
245 | <div class="action-buttons"> |
|
|||
246 | <div class="comment-button">${h.submit('save', _('Comment'), class_="btn btn-success comment-button-input")}</div> |
|
|||
247 | </div> |
|
|||
248 | </div> |
|
|||
249 | ${h.end_form()} |
|
|||
250 | </div> |
|
|||
251 |
|
|
217 | % else: | |
|
218 | ## form state when not logged in | |||
252 | <div class="comment-form ac"> |
|
219 | <div class="comment-form ac"> | |
253 |
|
220 | |||
254 | <div class="comment-area"> |
|
221 | <div class="comment-area"> | |
@@ -289,22 +256,98 b'' | |||||
289 | </div> |
|
256 | </div> | |
290 | % endif |
|
257 | % endif | |
291 |
|
258 | |||
|
259 | <script type="text/javascript"> | |||
|
260 | bindToggleButtons(); | |||
|
261 | </script> | |||
292 | </div> |
|
262 | </div> | |
|
263 | </%def> | |||
|
264 | ||||
|
265 | ||||
|
266 | <%def name="comment_form(form_type, form_id='', lineno_id='{1}', review_statuses=None, form_extras=None)"> | |||
|
267 | ## comment injected based on assumption that user is logged in | |||
|
268 | ||||
|
269 | <form ${'id="{}"'.format(form_id) if form_id else '' |n} action="#" method="GET"> | |||
293 |
|
270 | |||
294 | <script> |
|
271 | <div class="comment-area"> | |
295 | // init active elements of commentForm |
|
272 | <div class="comment-area-header"> | |
296 | var commitId = templateContext.commit_data.commit_id; |
|
273 | <ul class="nav-links clearfix"> | |
297 | var pullRequestId = templateContext.pull_request_data.pull_request_id; |
|
274 | <li class="active"> | |
298 | var lineNo; |
|
275 | <a href="#edit-btn" tabindex="-1" id="edit-btn_${lineno_id}">${_('Write')}</a> | |
|
276 | </li> | |||
|
277 | <li class=""> | |||
|
278 | <a href="#preview-btn" tabindex="-1" id="preview-btn_${lineno_id}">${_('Preview')}</a> | |||
|
279 | </li> | |||
|
280 | <li class="pull-right"> | |||
|
281 | <select class="comment-type" id="comment_type_${lineno_id}" name="comment_type"> | |||
|
282 | % for val in c.visual.comment_types: | |||
|
283 | <option value="${val}">${val.upper()}</option> | |||
|
284 | % endfor | |||
|
285 | </select> | |||
|
286 | </li> | |||
|
287 | </ul> | |||
|
288 | </div> | |||
|
289 | ||||
|
290 | <div class="comment-area-write" style="display: block;"> | |||
|
291 | <div id="edit-container_${lineno_id}"> | |||
|
292 | <textarea id="text_${lineno_id}" name="text" class="comment-block-ta ac-input"></textarea> | |||
|
293 | </div> | |||
|
294 | <div id="preview-container_${lineno_id}" class="clearfix" style="display: none;"> | |||
|
295 | <div id="preview-box_${lineno_id}" class="preview-box"></div> | |||
|
296 | </div> | |||
|
297 | </div> | |||
299 |
|
298 | |||
300 | var mainCommentForm = new CommentForm( |
|
299 | <div class="comment-area-footer"> | |
301 | "#${form_id}", commitId, pullRequestId, lineNo, true); |
|
300 | <div class="toolbar"> | |
|
301 | <div class="toolbar-text"> | |||
|
302 | ${(_('Comments parsed using %s syntax with %s support.') % ( | |||
|
303 | ('<a href="%s">%s</a>' % (h.url('%s_help' % c.visual.default_renderer), c.visual.default_renderer.upper())), | |||
|
304 | ('<span class="tooltip" title="%s">@mention</span>' % _('Use @username inside this text to send notification to this RhodeCode user')) | |||
|
305 | ) | |||
|
306 | )|n} | |||
|
307 | </div> | |||
|
308 | </div> | |||
|
309 | </div> | |||
|
310 | </div> | |||
|
311 | ||||
|
312 | <div class="comment-footer"> | |||
302 |
|
313 | |||
303 | if (mainCommentForm.cm){ |
|
314 | % if review_statuses: | |
304 | mainCommentForm.cm.setOption('placeholder', "${placeholder}"); |
|
315 | <div class="status_box"> | |
305 | } |
|
316 | <select id="change_status" name="changeset_status"> | |
|
317 | <option></option> ## Placeholder | |||
|
318 | % for status, lbl in review_statuses: | |||
|
319 | <option value="${status}" data-status="${status}">${lbl}</option> | |||
|
320 | %if is_pull_request and change_status and status in ('approved', 'rejected'): | |||
|
321 | <option value="${status}_closed" data-status="${status}">${lbl} & ${_('Closed')}</option> | |||
|
322 | %endif | |||
|
323 | % endfor | |||
|
324 | </select> | |||
|
325 | </div> | |||
|
326 | % endif | |||
306 |
|
327 | |||
307 | mainCommentForm.initStatusChangeSelector(); |
|
328 | ## inject extra inputs into the form | |
308 | bindToggleButtons(); |
|
329 | % if form_extras and isinstance(form_extras, (list, tuple)): | |
309 | </script> |
|
330 | <div id="comment_form_extras"> | |
310 | </%def> |
|
331 | % for form_ex_el in form_extras: | |
|
332 | ${form_ex_el|n} | |||
|
333 | % endfor | |||
|
334 | </div> | |||
|
335 | % endif | |||
|
336 | ||||
|
337 | <div class="action-buttons"> | |||
|
338 | ## inline for has a file, and line-number together with cancel hide button. | |||
|
339 | % if form_type == 'inline': | |||
|
340 | <input type="hidden" name="f_path" value="{0}"> | |||
|
341 | <input type="hidden" name="line" value="${lineno_id}"> | |||
|
342 | <button type="button" class="cb-comment-cancel" onclick="return Rhodecode.comments.cancelComment(this);"> | |||
|
343 | ${_('Cancel')} | |||
|
344 | </button> | |||
|
345 | % endif | |||
|
346 | ${h.submit('save', _('Comment'), class_='btn btn-success comment-button-input')} | |||
|
347 | ||||
|
348 | </div> | |||
|
349 | </div> | |||
|
350 | ||||
|
351 | </form> | |||
|
352 | ||||
|
353 | </%def> No newline at end of file |
@@ -1,3 +1,5 b'' | |||||
|
1 | <%namespace name="commentblock" file="/changeset/changeset_file_comment.mako"/> | |||
|
2 | ||||
1 | <%def name="diff_line_anchor(filename, line, type)"><% |
|
3 | <%def name="diff_line_anchor(filename, line, type)"><% | |
2 | return '%s_%s_%i' % (h.safeid(filename), type, line) |
|
4 | return '%s_%s_%i' % (h.safeid(filename), type, line) | |
3 | %></%def> |
|
5 | %></%def> | |
@@ -60,59 +62,8 b" return h.url('', **new_args)" | |||||
60 | <div class="comment-inline-form ac"> |
|
62 | <div class="comment-inline-form ac"> | |
61 |
|
63 | |||
62 | %if c.rhodecode_user.username != h.DEFAULT_USER: |
|
64 | %if c.rhodecode_user.username != h.DEFAULT_USER: | |
63 | ${h.form('#', method='get')} |
|
65 | ## render template for inline comments | |
64 | <div class="comment-area"> |
|
66 | ${commentblock.comment_form(form_type='inline')} | |
65 | <div class="comment-area-header"> |
|
|||
66 | <ul class="nav-links clearfix"> |
|
|||
67 | <li class="active"> |
|
|||
68 | <a href="#edit-btn" tabindex="-1" id="edit-btn_{1}">${_('Write')}</a> |
|
|||
69 | </li> |
|
|||
70 | <li class=""> |
|
|||
71 | <a href="#preview-btn" tabindex="-1" id="preview-btn_{1}">${_('Preview')}</a> |
|
|||
72 | </li> |
|
|||
73 | <li class="pull-right"> |
|
|||
74 | <select class="comment-type" id="comment_type_{1}" name="comment_type"> |
|
|||
75 | % for val in c.visual.comment_types: |
|
|||
76 | <option value="${val}">${val.upper()}</option> |
|
|||
77 | % endfor |
|
|||
78 | </select> |
|
|||
79 | </li> |
|
|||
80 | </ul> |
|
|||
81 | </div> |
|
|||
82 |
|
||||
83 | <div class="comment-area-write" style="display: block;"> |
|
|||
84 | <div id="edit-container_{1}"> |
|
|||
85 | <textarea id="text_{1}" name="text" class="comment-block-ta ac-input"></textarea> |
|
|||
86 | </div> |
|
|||
87 | <div id="preview-container_{1}" class="clearfix" style="display: none;"> |
|
|||
88 | <div id="preview-box_{1}" class="preview-box"></div> |
|
|||
89 | </div> |
|
|||
90 | </div> |
|
|||
91 |
|
||||
92 | <div class="comment-area-footer"> |
|
|||
93 | <div class="toolbar"> |
|
|||
94 | <div class="toolbar-text"> |
|
|||
95 | ${(_('Comments parsed using %s syntax with %s support.') % ( |
|
|||
96 | ('<a href="%s">%s</a>' % (h.url('%s_help' % c.visual.default_renderer), c.visual.default_renderer.upper())), |
|
|||
97 | ('<span class="tooltip" title="%s">@mention</span>' % _('Use @username inside this text to send notification to this RhodeCode user')) |
|
|||
98 | ) |
|
|||
99 | )|n} |
|
|||
100 | </div> |
|
|||
101 | </div> |
|
|||
102 | </div> |
|
|||
103 | </div> |
|
|||
104 |
|
||||
105 | <div class="comment-footer"> |
|
|||
106 | <div class="action-buttons"> |
|
|||
107 | <input type="hidden" name="f_path" value="{0}"> |
|
|||
108 | <input type="hidden" name="line" value="{1}"> |
|
|||
109 | <button type="button" class="cb-comment-cancel" onclick="return Rhodecode.comments.cancelComment(this);"> |
|
|||
110 | ${_('Cancel')} |
|
|||
111 | </button> |
|
|||
112 | ${h.submit('save', _('Comment'), class_='btn btn-success save-inline-form')} |
|
|||
113 | </div> |
|
|||
114 | ${h.end_form()} |
|
|||
115 | </div> |
|
|||
116 |
|
|
67 | %else: | |
117 | ${h.form('', class_='inline-form comment-form-login', method='get')} |
|
68 | ${h.form('', class_='inline-form comment-form-login', method='get')} | |
118 | <div class="pull-left"> |
|
69 | <div class="pull-left"> | |
@@ -521,7 +472,6 b' from rhodecode.lib.diffs import NEW_FILE' | |||||
521 | </%def> |
|
472 | </%def> | |
522 |
|
473 | |||
523 |
|
474 | |||
524 | <%namespace name="commentblock" file="/changeset/changeset_file_comment.mako"/> |
|
|||
525 | <%def name="inline_comments_container(comments)"> |
|
475 | <%def name="inline_comments_container(comments)"> | |
526 | <div class="inline-comments"> |
|
476 | <div class="inline-comments"> | |
527 | %for comment in comments: |
|
477 | %for comment in comments: |
General Comments 0
You need to be logged in to leave comments.
Login now