##// END OF EJS Templates
comments: updated edit message when body is still the same.
marcink -
r4403:dc3600c4 default
parent child Browse files
Show More
@@ -1,1202 +1,1202 b''
1 // # Copyright (C) 2010-2020 RhodeCode GmbH
1 // # Copyright (C) 2010-2020 RhodeCode GmbH
2 // #
2 // #
3 // # This program is free software: you can redistribute it and/or modify
3 // # This program is free software: you can redistribute it and/or modify
4 // # it under the terms of the GNU Affero General Public License, version 3
4 // # it under the terms of the GNU Affero General Public License, version 3
5 // # (only), as published by the Free Software Foundation.
5 // # (only), as published by the Free Software Foundation.
6 // #
6 // #
7 // # This program is distributed in the hope that it will be useful,
7 // # This program is distributed in the hope that it will be useful,
8 // # but WITHOUT ANY WARRANTY; without even the implied warranty of
8 // # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 // # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 // # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 // # GNU General Public License for more details.
10 // # GNU General Public License for more details.
11 // #
11 // #
12 // # You should have received a copy of the GNU Affero General Public License
12 // # You should have received a copy of the GNU Affero General Public License
13 // # along with this program. If not, see <http://www.gnu.org/licenses/>.
13 // # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 // #
14 // #
15 // # This program is dual-licensed. If you wish to learn more about the
15 // # This program is dual-licensed. If you wish to learn more about the
16 // # RhodeCode Enterprise Edition, including its added features, Support services,
16 // # RhodeCode Enterprise Edition, including its added features, Support services,
17 // # and proprietary license terms, please see https://rhodecode.com/licenses/
17 // # and proprietary license terms, please see https://rhodecode.com/licenses/
18
18
19 var firefoxAnchorFix = function() {
19 var firefoxAnchorFix = function() {
20 // hack to make anchor links behave properly on firefox, in our inline
20 // hack to make anchor links behave properly on firefox, in our inline
21 // comments generation when comments are injected firefox is misbehaving
21 // comments generation when comments are injected firefox is misbehaving
22 // when jumping to anchor links
22 // when jumping to anchor links
23 if (location.href.indexOf('#') > -1) {
23 if (location.href.indexOf('#') > -1) {
24 location.href += '';
24 location.href += '';
25 }
25 }
26 };
26 };
27
27
28 var linkifyComments = function(comments) {
28 var linkifyComments = function(comments) {
29 var firstCommentId = null;
29 var firstCommentId = null;
30 if (comments) {
30 if (comments) {
31 firstCommentId = $(comments[0]).data('comment-id');
31 firstCommentId = $(comments[0]).data('comment-id');
32 }
32 }
33
33
34 if (firstCommentId){
34 if (firstCommentId){
35 $('#inline-comments-counter').attr('href', '#comment-' + firstCommentId);
35 $('#inline-comments-counter').attr('href', '#comment-' + firstCommentId);
36 }
36 }
37 };
37 };
38
38
39 var bindToggleButtons = function() {
39 var bindToggleButtons = function() {
40 $('.comment-toggle').on('click', function() {
40 $('.comment-toggle').on('click', function() {
41 $(this).parent().nextUntil('tr.line').toggle('inline-comments');
41 $(this).parent().nextUntil('tr.line').toggle('inline-comments');
42 });
42 });
43 };
43 };
44
44
45
45
46
46
47 var _submitAjaxPOST = function(url, postData, successHandler, failHandler) {
47 var _submitAjaxPOST = function(url, postData, successHandler, failHandler) {
48 failHandler = failHandler || function() {};
48 failHandler = failHandler || function() {};
49 postData = toQueryString(postData);
49 postData = toQueryString(postData);
50 var request = $.ajax({
50 var request = $.ajax({
51 url: url,
51 url: url,
52 type: 'POST',
52 type: 'POST',
53 data: postData,
53 data: postData,
54 headers: {'X-PARTIAL-XHR': true}
54 headers: {'X-PARTIAL-XHR': true}
55 })
55 })
56 .done(function (data) {
56 .done(function (data) {
57 successHandler(data);
57 successHandler(data);
58 })
58 })
59 .fail(function (data, textStatus, errorThrown) {
59 .fail(function (data, textStatus, errorThrown) {
60 failHandler(data, textStatus, errorThrown)
60 failHandler(data, textStatus, errorThrown)
61 });
61 });
62 return request;
62 return request;
63 };
63 };
64
64
65
65
66
66
67
67
68 /* Comment form for main and inline comments */
68 /* Comment form for main and inline comments */
69 (function(mod) {
69 (function(mod) {
70
70
71 if (typeof exports == "object" && typeof module == "object") {
71 if (typeof exports == "object" && typeof module == "object") {
72 // CommonJS
72 // CommonJS
73 module.exports = mod();
73 module.exports = mod();
74 }
74 }
75 else {
75 else {
76 // Plain browser env
76 // Plain browser env
77 (this || window).CommentForm = mod();
77 (this || window).CommentForm = mod();
78 }
78 }
79
79
80 })(function() {
80 })(function() {
81 "use strict";
81 "use strict";
82
82
83 function CommentForm(formElement, commitId, pullRequestId, lineNo, initAutocompleteActions, resolvesCommentId, edit, comment_id) {
83 function CommentForm(formElement, commitId, pullRequestId, lineNo, initAutocompleteActions, resolvesCommentId, edit, comment_id) {
84
84
85 if (!(this instanceof CommentForm)) {
85 if (!(this instanceof CommentForm)) {
86 return new CommentForm(formElement, commitId, pullRequestId, lineNo, initAutocompleteActions, resolvesCommentId, edit, comment_id);
86 return new CommentForm(formElement, commitId, pullRequestId, lineNo, initAutocompleteActions, resolvesCommentId, edit, comment_id);
87 }
87 }
88
88
89 // bind the element instance to our Form
89 // bind the element instance to our Form
90 $(formElement).get(0).CommentForm = this;
90 $(formElement).get(0).CommentForm = this;
91
91
92 this.withLineNo = function(selector) {
92 this.withLineNo = function(selector) {
93 var lineNo = this.lineNo;
93 var lineNo = this.lineNo;
94 if (lineNo === undefined) {
94 if (lineNo === undefined) {
95 return selector
95 return selector
96 } else {
96 } else {
97 return selector + '_' + lineNo;
97 return selector + '_' + lineNo;
98 }
98 }
99 };
99 };
100
100
101 this.commitId = commitId;
101 this.commitId = commitId;
102 this.pullRequestId = pullRequestId;
102 this.pullRequestId = pullRequestId;
103 this.lineNo = lineNo;
103 this.lineNo = lineNo;
104 this.initAutocompleteActions = initAutocompleteActions;
104 this.initAutocompleteActions = initAutocompleteActions;
105
105
106 this.previewButton = this.withLineNo('#preview-btn');
106 this.previewButton = this.withLineNo('#preview-btn');
107 this.previewContainer = this.withLineNo('#preview-container');
107 this.previewContainer = this.withLineNo('#preview-container');
108
108
109 this.previewBoxSelector = this.withLineNo('#preview-box');
109 this.previewBoxSelector = this.withLineNo('#preview-box');
110
110
111 this.editButton = this.withLineNo('#edit-btn');
111 this.editButton = this.withLineNo('#edit-btn');
112 this.editContainer = this.withLineNo('#edit-container');
112 this.editContainer = this.withLineNo('#edit-container');
113 this.cancelButton = this.withLineNo('#cancel-btn');
113 this.cancelButton = this.withLineNo('#cancel-btn');
114 this.commentType = this.withLineNo('#comment_type');
114 this.commentType = this.withLineNo('#comment_type');
115
115
116 this.resolvesId = null;
116 this.resolvesId = null;
117 this.resolvesActionId = null;
117 this.resolvesActionId = null;
118
118
119 this.closesPr = '#close_pull_request';
119 this.closesPr = '#close_pull_request';
120
120
121 this.cmBox = this.withLineNo('#text');
121 this.cmBox = this.withLineNo('#text');
122 this.cm = initCommentBoxCodeMirror(this, this.cmBox, this.initAutocompleteActions);
122 this.cm = initCommentBoxCodeMirror(this, this.cmBox, this.initAutocompleteActions);
123
123
124 this.statusChange = this.withLineNo('#change_status');
124 this.statusChange = this.withLineNo('#change_status');
125
125
126 this.submitForm = formElement;
126 this.submitForm = formElement;
127 this.submitButton = $(this.submitForm).find('input[type="submit"]');
127 this.submitButton = $(this.submitForm).find('input[type="submit"]');
128 this.submitButtonText = this.submitButton.val();
128 this.submitButtonText = this.submitButton.val();
129
129
130
130
131 this.previewUrl = pyroutes.url('repo_commit_comment_preview',
131 this.previewUrl = pyroutes.url('repo_commit_comment_preview',
132 {'repo_name': templateContext.repo_name,
132 {'repo_name': templateContext.repo_name,
133 'commit_id': templateContext.commit_data.commit_id});
133 'commit_id': templateContext.commit_data.commit_id});
134
134
135 if (edit){
135 if (edit){
136 this.submitButtonText = _gettext('Updated Comment');
136 this.submitButtonText = _gettext('Updated Comment');
137 $(this.commentType).prop('disabled', true);
137 $(this.commentType).prop('disabled', true);
138 $(this.commentType).addClass('disabled');
138 $(this.commentType).addClass('disabled');
139 var editInfo =
139 var editInfo =
140 '<div class="comment-label note" id="comment-label-6" title="line: ">' +
140 '<div class="comment-label note" id="comment-label-6" title="line: ">' +
141 'editing' +
141 'editing' +
142 '</div>';
142 '</div>';
143 $(editInfo).insertBefore($(this.editButton).parent());
143 $(editInfo).insertBefore($(this.editButton).parent());
144 }
144 }
145
145
146 if (resolvesCommentId){
146 if (resolvesCommentId){
147 this.resolvesId = '#resolve_comment_{0}'.format(resolvesCommentId);
147 this.resolvesId = '#resolve_comment_{0}'.format(resolvesCommentId);
148 this.resolvesActionId = '#resolve_comment_action_{0}'.format(resolvesCommentId);
148 this.resolvesActionId = '#resolve_comment_action_{0}'.format(resolvesCommentId);
149 $(this.commentType).prop('disabled', true);
149 $(this.commentType).prop('disabled', true);
150 $(this.commentType).addClass('disabled');
150 $(this.commentType).addClass('disabled');
151
151
152 // disable select
152 // disable select
153 setTimeout(function() {
153 setTimeout(function() {
154 $(self.statusChange).select2('readonly', true);
154 $(self.statusChange).select2('readonly', true);
155 }, 10);
155 }, 10);
156
156
157 var resolvedInfo = (
157 var resolvedInfo = (
158 '<li class="resolve-action">' +
158 '<li class="resolve-action">' +
159 '<input type="hidden" id="resolve_comment_{0}" name="resolve_comment_{0}" value="{0}">' +
159 '<input type="hidden" id="resolve_comment_{0}" name="resolve_comment_{0}" value="{0}">' +
160 '<button id="resolve_comment_action_{0}" class="resolve-text btn btn-sm" onclick="return Rhodecode.comments.submitResolution({0})">{1} #{0}</button>' +
160 '<button id="resolve_comment_action_{0}" class="resolve-text btn btn-sm" onclick="return Rhodecode.comments.submitResolution({0})">{1} #{0}</button>' +
161 '</li>'
161 '</li>'
162 ).format(resolvesCommentId, _gettext('resolve comment'));
162 ).format(resolvesCommentId, _gettext('resolve comment'));
163 $(resolvedInfo).insertAfter($(this.commentType).parent());
163 $(resolvedInfo).insertAfter($(this.commentType).parent());
164 }
164 }
165
165
166 // based on commitId, or pullRequestId decide where do we submit
166 // based on commitId, or pullRequestId decide where do we submit
167 // out data
167 // out data
168 if (this.commitId){
168 if (this.commitId){
169 var pyurl = 'repo_commit_comment_create';
169 var pyurl = 'repo_commit_comment_create';
170 if(edit){
170 if(edit){
171 pyurl = 'repo_commit_comment_edit';
171 pyurl = 'repo_commit_comment_edit';
172 }
172 }
173 this.submitUrl = pyroutes.url(pyurl,
173 this.submitUrl = pyroutes.url(pyurl,
174 {'repo_name': templateContext.repo_name,
174 {'repo_name': templateContext.repo_name,
175 'commit_id': this.commitId,
175 'commit_id': this.commitId,
176 'comment_id': comment_id});
176 'comment_id': comment_id});
177 this.selfUrl = pyroutes.url('repo_commit',
177 this.selfUrl = pyroutes.url('repo_commit',
178 {'repo_name': templateContext.repo_name,
178 {'repo_name': templateContext.repo_name,
179 'commit_id': this.commitId});
179 'commit_id': this.commitId});
180
180
181 } else if (this.pullRequestId) {
181 } else if (this.pullRequestId) {
182 var pyurl = 'pullrequest_comment_create';
182 var pyurl = 'pullrequest_comment_create';
183 if(edit){
183 if(edit){
184 pyurl = 'pullrequest_comment_edit';
184 pyurl = 'pullrequest_comment_edit';
185 }
185 }
186 this.submitUrl = pyroutes.url(pyurl,
186 this.submitUrl = pyroutes.url(pyurl,
187 {'repo_name': templateContext.repo_name,
187 {'repo_name': templateContext.repo_name,
188 'pull_request_id': this.pullRequestId,
188 'pull_request_id': this.pullRequestId,
189 'comment_id': comment_id});
189 'comment_id': comment_id});
190 this.selfUrl = pyroutes.url('pullrequest_show',
190 this.selfUrl = pyroutes.url('pullrequest_show',
191 {'repo_name': templateContext.repo_name,
191 {'repo_name': templateContext.repo_name,
192 'pull_request_id': this.pullRequestId});
192 'pull_request_id': this.pullRequestId});
193
193
194 } else {
194 } else {
195 throw new Error(
195 throw new Error(
196 'CommentForm requires pullRequestId, or commitId to be specified.')
196 'CommentForm requires pullRequestId, or commitId to be specified.')
197 }
197 }
198
198
199 // FUNCTIONS and helpers
199 // FUNCTIONS and helpers
200 var self = this;
200 var self = this;
201
201
202 this.isInline = function(){
202 this.isInline = function(){
203 return this.lineNo && this.lineNo != 'general';
203 return this.lineNo && this.lineNo != 'general';
204 };
204 };
205
205
206 this.getCmInstance = function(){
206 this.getCmInstance = function(){
207 return this.cm
207 return this.cm
208 };
208 };
209
209
210 this.setPlaceholder = function(placeholder) {
210 this.setPlaceholder = function(placeholder) {
211 var cm = this.getCmInstance();
211 var cm = this.getCmInstance();
212 if (cm){
212 if (cm){
213 cm.setOption('placeholder', placeholder);
213 cm.setOption('placeholder', placeholder);
214 }
214 }
215 };
215 };
216
216
217 this.getCommentStatus = function() {
217 this.getCommentStatus = function() {
218 return $(this.submitForm).find(this.statusChange).val();
218 return $(this.submitForm).find(this.statusChange).val();
219 };
219 };
220 this.getCommentType = function() {
220 this.getCommentType = function() {
221 return $(this.submitForm).find(this.commentType).val();
221 return $(this.submitForm).find(this.commentType).val();
222 };
222 };
223
223
224 this.getResolvesId = function() {
224 this.getResolvesId = function() {
225 return $(this.submitForm).find(this.resolvesId).val() || null;
225 return $(this.submitForm).find(this.resolvesId).val() || null;
226 };
226 };
227
227
228 this.getClosePr = function() {
228 this.getClosePr = function() {
229 return $(this.submitForm).find(this.closesPr).val() || null;
229 return $(this.submitForm).find(this.closesPr).val() || null;
230 };
230 };
231
231
232 this.markCommentResolved = function(resolvedCommentId){
232 this.markCommentResolved = function(resolvedCommentId){
233 $('#comment-label-{0}'.format(resolvedCommentId)).find('.resolved').show();
233 $('#comment-label-{0}'.format(resolvedCommentId)).find('.resolved').show();
234 $('#comment-label-{0}'.format(resolvedCommentId)).find('.resolve').hide();
234 $('#comment-label-{0}'.format(resolvedCommentId)).find('.resolve').hide();
235 };
235 };
236
236
237 this.isAllowedToSubmit = function() {
237 this.isAllowedToSubmit = function() {
238 return !$(this.submitButton).prop('disabled');
238 return !$(this.submitButton).prop('disabled');
239 };
239 };
240
240
241 this.initStatusChangeSelector = function(){
241 this.initStatusChangeSelector = function(){
242 var formatChangeStatus = function(state, escapeMarkup) {
242 var formatChangeStatus = function(state, escapeMarkup) {
243 var originalOption = state.element;
243 var originalOption = state.element;
244 var tmpl = '<i class="icon-circle review-status-{0}"></i><span>{1}</span>'.format($(originalOption).data('status'), escapeMarkup(state.text));
244 var tmpl = '<i class="icon-circle review-status-{0}"></i><span>{1}</span>'.format($(originalOption).data('status'), escapeMarkup(state.text));
245 return tmpl
245 return tmpl
246 };
246 };
247 var formatResult = function(result, container, query, escapeMarkup) {
247 var formatResult = function(result, container, query, escapeMarkup) {
248 return formatChangeStatus(result, escapeMarkup);
248 return formatChangeStatus(result, escapeMarkup);
249 };
249 };
250
250
251 var formatSelection = function(data, container, escapeMarkup) {
251 var formatSelection = function(data, container, escapeMarkup) {
252 return formatChangeStatus(data, escapeMarkup);
252 return formatChangeStatus(data, escapeMarkup);
253 };
253 };
254
254
255 $(this.submitForm).find(this.statusChange).select2({
255 $(this.submitForm).find(this.statusChange).select2({
256 placeholder: _gettext('Status Review'),
256 placeholder: _gettext('Status Review'),
257 formatResult: formatResult,
257 formatResult: formatResult,
258 formatSelection: formatSelection,
258 formatSelection: formatSelection,
259 containerCssClass: "drop-menu status_box_menu",
259 containerCssClass: "drop-menu status_box_menu",
260 dropdownCssClass: "drop-menu-dropdown",
260 dropdownCssClass: "drop-menu-dropdown",
261 dropdownAutoWidth: true,
261 dropdownAutoWidth: true,
262 minimumResultsForSearch: -1
262 minimumResultsForSearch: -1
263 });
263 });
264 $(this.submitForm).find(this.statusChange).on('change', function() {
264 $(this.submitForm).find(this.statusChange).on('change', function() {
265 var status = self.getCommentStatus();
265 var status = self.getCommentStatus();
266
266
267 if (status && !self.isInline()) {
267 if (status && !self.isInline()) {
268 $(self.submitButton).prop('disabled', false);
268 $(self.submitButton).prop('disabled', false);
269 }
269 }
270
270
271 var placeholderText = _gettext('Comment text will be set automatically based on currently selected status ({0}) ...').format(status);
271 var placeholderText = _gettext('Comment text will be set automatically based on currently selected status ({0}) ...').format(status);
272 self.setPlaceholder(placeholderText)
272 self.setPlaceholder(placeholderText)
273 })
273 })
274 };
274 };
275
275
276 // reset the comment form into it's original state
276 // reset the comment form into it's original state
277 this.resetCommentFormState = function(content) {
277 this.resetCommentFormState = function(content) {
278 content = content || '';
278 content = content || '';
279
279
280 $(this.editContainer).show();
280 $(this.editContainer).show();
281 $(this.editButton).parent().addClass('active');
281 $(this.editButton).parent().addClass('active');
282
282
283 $(this.previewContainer).hide();
283 $(this.previewContainer).hide();
284 $(this.previewButton).parent().removeClass('active');
284 $(this.previewButton).parent().removeClass('active');
285
285
286 this.setActionButtonsDisabled(true);
286 this.setActionButtonsDisabled(true);
287 self.cm.setValue(content);
287 self.cm.setValue(content);
288 self.cm.setOption("readOnly", false);
288 self.cm.setOption("readOnly", false);
289
289
290 if (this.resolvesId) {
290 if (this.resolvesId) {
291 // destroy the resolve action
291 // destroy the resolve action
292 $(this.resolvesId).parent().remove();
292 $(this.resolvesId).parent().remove();
293 }
293 }
294 // reset closingPR flag
294 // reset closingPR flag
295 $('.close-pr-input').remove();
295 $('.close-pr-input').remove();
296
296
297 $(this.statusChange).select2('readonly', false);
297 $(this.statusChange).select2('readonly', false);
298 };
298 };
299
299
300 this.globalSubmitSuccessCallback = function(){
300 this.globalSubmitSuccessCallback = function(){
301 // default behaviour is to call GLOBAL hook, if it's registered.
301 // default behaviour is to call GLOBAL hook, if it's registered.
302 if (window.commentFormGlobalSubmitSuccessCallback !== undefined){
302 if (window.commentFormGlobalSubmitSuccessCallback !== undefined){
303 commentFormGlobalSubmitSuccessCallback();
303 commentFormGlobalSubmitSuccessCallback();
304 }
304 }
305 };
305 };
306
306
307 this.submitAjaxPOST = function(url, postData, successHandler, failHandler) {
307 this.submitAjaxPOST = function(url, postData, successHandler, failHandler) {
308 return _submitAjaxPOST(url, postData, successHandler, failHandler);
308 return _submitAjaxPOST(url, postData, successHandler, failHandler);
309 };
309 };
310
310
311 // overwrite a submitHandler, we need to do it for inline comments
311 // overwrite a submitHandler, we need to do it for inline comments
312 this.setHandleFormSubmit = function(callback) {
312 this.setHandleFormSubmit = function(callback) {
313 this.handleFormSubmit = callback;
313 this.handleFormSubmit = callback;
314 };
314 };
315
315
316 // overwrite a submitSuccessHandler
316 // overwrite a submitSuccessHandler
317 this.setGlobalSubmitSuccessCallback = function(callback) {
317 this.setGlobalSubmitSuccessCallback = function(callback) {
318 this.globalSubmitSuccessCallback = callback;
318 this.globalSubmitSuccessCallback = callback;
319 };
319 };
320
320
321 // default handler for for submit for main comments
321 // default handler for for submit for main comments
322 this.handleFormSubmit = function() {
322 this.handleFormSubmit = function() {
323 var text = self.cm.getValue();
323 var text = self.cm.getValue();
324 var status = self.getCommentStatus();
324 var status = self.getCommentStatus();
325 var commentType = self.getCommentType();
325 var commentType = self.getCommentType();
326 var resolvesCommentId = self.getResolvesId();
326 var resolvesCommentId = self.getResolvesId();
327 var closePullRequest = self.getClosePr();
327 var closePullRequest = self.getClosePr();
328
328
329 if (text === "" && !status) {
329 if (text === "" && !status) {
330 return;
330 return;
331 }
331 }
332
332
333 var excludeCancelBtn = false;
333 var excludeCancelBtn = false;
334 var submitEvent = true;
334 var submitEvent = true;
335 self.setActionButtonsDisabled(true, excludeCancelBtn, submitEvent);
335 self.setActionButtonsDisabled(true, excludeCancelBtn, submitEvent);
336 self.cm.setOption("readOnly", true);
336 self.cm.setOption("readOnly", true);
337
337
338 var postData = {
338 var postData = {
339 'text': text,
339 'text': text,
340 'changeset_status': status,
340 'changeset_status': status,
341 'comment_type': commentType,
341 'comment_type': commentType,
342 'csrf_token': CSRF_TOKEN
342 'csrf_token': CSRF_TOKEN
343 };
343 };
344
344
345 if (resolvesCommentId) {
345 if (resolvesCommentId) {
346 postData['resolves_comment_id'] = resolvesCommentId;
346 postData['resolves_comment_id'] = resolvesCommentId;
347 }
347 }
348
348
349 if (closePullRequest) {
349 if (closePullRequest) {
350 postData['close_pull_request'] = true;
350 postData['close_pull_request'] = true;
351 }
351 }
352
352
353 var submitSuccessCallback = function(o) {
353 var submitSuccessCallback = function(o) {
354 // reload page if we change status for single commit.
354 // reload page if we change status for single commit.
355 if (status && self.commitId) {
355 if (status && self.commitId) {
356 location.reload(true);
356 location.reload(true);
357 } else {
357 } else {
358 $('#injected_page_comments').append(o.rendered_text);
358 $('#injected_page_comments').append(o.rendered_text);
359 self.resetCommentFormState();
359 self.resetCommentFormState();
360 timeagoActivate();
360 timeagoActivate();
361 tooltipActivate();
361 tooltipActivate();
362
362
363 // mark visually which comment was resolved
363 // mark visually which comment was resolved
364 if (resolvesCommentId) {
364 if (resolvesCommentId) {
365 self.markCommentResolved(resolvesCommentId);
365 self.markCommentResolved(resolvesCommentId);
366 }
366 }
367 }
367 }
368
368
369 // run global callback on submit
369 // run global callback on submit
370 self.globalSubmitSuccessCallback();
370 self.globalSubmitSuccessCallback();
371
371
372 };
372 };
373 var submitFailCallback = function(jqXHR, textStatus, errorThrown) {
373 var submitFailCallback = function(jqXHR, textStatus, errorThrown) {
374 var prefix = "Error while submitting comment.\n"
374 var prefix = "Error while submitting comment.\n"
375 var message = formatErrorMessage(jqXHR, textStatus, errorThrown, prefix);
375 var message = formatErrorMessage(jqXHR, textStatus, errorThrown, prefix);
376 ajaxErrorSwal(message);
376 ajaxErrorSwal(message);
377 self.resetCommentFormState(text);
377 self.resetCommentFormState(text);
378 };
378 };
379 self.submitAjaxPOST(
379 self.submitAjaxPOST(
380 self.submitUrl, postData, submitSuccessCallback, submitFailCallback);
380 self.submitUrl, postData, submitSuccessCallback, submitFailCallback);
381 };
381 };
382
382
383 this.previewSuccessCallback = function(o) {
383 this.previewSuccessCallback = function(o) {
384 $(self.previewBoxSelector).html(o);
384 $(self.previewBoxSelector).html(o);
385 $(self.previewBoxSelector).removeClass('unloaded');
385 $(self.previewBoxSelector).removeClass('unloaded');
386
386
387 // swap buttons, making preview active
387 // swap buttons, making preview active
388 $(self.previewButton).parent().addClass('active');
388 $(self.previewButton).parent().addClass('active');
389 $(self.editButton).parent().removeClass('active');
389 $(self.editButton).parent().removeClass('active');
390
390
391 // unlock buttons
391 // unlock buttons
392 self.setActionButtonsDisabled(false);
392 self.setActionButtonsDisabled(false);
393 };
393 };
394
394
395 this.setActionButtonsDisabled = function(state, excludeCancelBtn, submitEvent) {
395 this.setActionButtonsDisabled = function(state, excludeCancelBtn, submitEvent) {
396 excludeCancelBtn = excludeCancelBtn || false;
396 excludeCancelBtn = excludeCancelBtn || false;
397 submitEvent = submitEvent || false;
397 submitEvent = submitEvent || false;
398
398
399 $(this.editButton).prop('disabled', state);
399 $(this.editButton).prop('disabled', state);
400 $(this.previewButton).prop('disabled', state);
400 $(this.previewButton).prop('disabled', state);
401
401
402 if (!excludeCancelBtn) {
402 if (!excludeCancelBtn) {
403 $(this.cancelButton).prop('disabled', state);
403 $(this.cancelButton).prop('disabled', state);
404 }
404 }
405
405
406 var submitState = state;
406 var submitState = state;
407 if (!submitEvent && this.getCommentStatus() && !self.isInline()) {
407 if (!submitEvent && this.getCommentStatus() && !self.isInline()) {
408 // if the value of commit review status is set, we allow
408 // if the value of commit review status is set, we allow
409 // submit button, but only on Main form, isInline means inline
409 // submit button, but only on Main form, isInline means inline
410 submitState = false
410 submitState = false
411 }
411 }
412
412
413 $(this.submitButton).prop('disabled', submitState);
413 $(this.submitButton).prop('disabled', submitState);
414 if (submitEvent) {
414 if (submitEvent) {
415 $(this.submitButton).val(_gettext('Submitting...'));
415 $(this.submitButton).val(_gettext('Submitting...'));
416 } else {
416 } else {
417 $(this.submitButton).val(this.submitButtonText);
417 $(this.submitButton).val(this.submitButtonText);
418 }
418 }
419
419
420 };
420 };
421
421
422 // lock preview/edit/submit buttons on load, but exclude cancel button
422 // lock preview/edit/submit buttons on load, but exclude cancel button
423 var excludeCancelBtn = true;
423 var excludeCancelBtn = true;
424 this.setActionButtonsDisabled(true, excludeCancelBtn);
424 this.setActionButtonsDisabled(true, excludeCancelBtn);
425
425
426 // anonymous users don't have access to initialized CM instance
426 // anonymous users don't have access to initialized CM instance
427 if (this.cm !== undefined){
427 if (this.cm !== undefined){
428 this.cm.on('change', function(cMirror) {
428 this.cm.on('change', function(cMirror) {
429 if (cMirror.getValue() === "") {
429 if (cMirror.getValue() === "") {
430 self.setActionButtonsDisabled(true, excludeCancelBtn)
430 self.setActionButtonsDisabled(true, excludeCancelBtn)
431 } else {
431 } else {
432 self.setActionButtonsDisabled(false, excludeCancelBtn)
432 self.setActionButtonsDisabled(false, excludeCancelBtn)
433 }
433 }
434 });
434 });
435 }
435 }
436
436
437 $(this.editButton).on('click', function(e) {
437 $(this.editButton).on('click', function(e) {
438 e.preventDefault();
438 e.preventDefault();
439
439
440 $(self.previewButton).parent().removeClass('active');
440 $(self.previewButton).parent().removeClass('active');
441 $(self.previewContainer).hide();
441 $(self.previewContainer).hide();
442
442
443 $(self.editButton).parent().addClass('active');
443 $(self.editButton).parent().addClass('active');
444 $(self.editContainer).show();
444 $(self.editContainer).show();
445
445
446 });
446 });
447
447
448 $(this.previewButton).on('click', function(e) {
448 $(this.previewButton).on('click', function(e) {
449 e.preventDefault();
449 e.preventDefault();
450 var text = self.cm.getValue();
450 var text = self.cm.getValue();
451
451
452 if (text === "") {
452 if (text === "") {
453 return;
453 return;
454 }
454 }
455
455
456 var postData = {
456 var postData = {
457 'text': text,
457 'text': text,
458 'renderer': templateContext.visual.default_renderer,
458 'renderer': templateContext.visual.default_renderer,
459 'csrf_token': CSRF_TOKEN
459 'csrf_token': CSRF_TOKEN
460 };
460 };
461
461
462 // lock ALL buttons on preview
462 // lock ALL buttons on preview
463 self.setActionButtonsDisabled(true);
463 self.setActionButtonsDisabled(true);
464
464
465 $(self.previewBoxSelector).addClass('unloaded');
465 $(self.previewBoxSelector).addClass('unloaded');
466 $(self.previewBoxSelector).html(_gettext('Loading ...'));
466 $(self.previewBoxSelector).html(_gettext('Loading ...'));
467
467
468 $(self.editContainer).hide();
468 $(self.editContainer).hide();
469 $(self.previewContainer).show();
469 $(self.previewContainer).show();
470
470
471 // by default we reset state of comment preserving the text
471 // by default we reset state of comment preserving the text
472 var previewFailCallback = function(jqXHR, textStatus, errorThrown) {
472 var previewFailCallback = function(jqXHR, textStatus, errorThrown) {
473 var prefix = "Error while preview of comment.\n"
473 var prefix = "Error while preview of comment.\n"
474 var message = formatErrorMessage(jqXHR, textStatus, errorThrown, prefix);
474 var message = formatErrorMessage(jqXHR, textStatus, errorThrown, prefix);
475 ajaxErrorSwal(message);
475 ajaxErrorSwal(message);
476
476
477 self.resetCommentFormState(text)
477 self.resetCommentFormState(text)
478 };
478 };
479 self.submitAjaxPOST(
479 self.submitAjaxPOST(
480 self.previewUrl, postData, self.previewSuccessCallback,
480 self.previewUrl, postData, self.previewSuccessCallback,
481 previewFailCallback);
481 previewFailCallback);
482
482
483 $(self.previewButton).parent().addClass('active');
483 $(self.previewButton).parent().addClass('active');
484 $(self.editButton).parent().removeClass('active');
484 $(self.editButton).parent().removeClass('active');
485 });
485 });
486
486
487 $(this.submitForm).submit(function(e) {
487 $(this.submitForm).submit(function(e) {
488 e.preventDefault();
488 e.preventDefault();
489 var allowedToSubmit = self.isAllowedToSubmit();
489 var allowedToSubmit = self.isAllowedToSubmit();
490 if (!allowedToSubmit){
490 if (!allowedToSubmit){
491 return false;
491 return false;
492 }
492 }
493 self.handleFormSubmit();
493 self.handleFormSubmit();
494 });
494 });
495
495
496 }
496 }
497
497
498 return CommentForm;
498 return CommentForm;
499 });
499 });
500
500
501 /* comments controller */
501 /* comments controller */
502 var CommentsController = function() {
502 var CommentsController = function() {
503 var mainComment = '#text';
503 var mainComment = '#text';
504 var self = this;
504 var self = this;
505
505
506 this.cancelComment = function (node) {
506 this.cancelComment = function (node) {
507 var $node = $(node);
507 var $node = $(node);
508 var edit = $(this).attr('edit');
508 var edit = $(this).attr('edit');
509 if (edit) {
509 if (edit) {
510 var $general_comments = null;
510 var $general_comments = null;
511 var $inline_comments = $node.closest('div.inline-comments');
511 var $inline_comments = $node.closest('div.inline-comments');
512 if (!$inline_comments.length) {
512 if (!$inline_comments.length) {
513 $general_comments = $('#comments');
513 $general_comments = $('#comments');
514 var $comment = $general_comments.parent().find('div.comment:hidden');
514 var $comment = $general_comments.parent().find('div.comment:hidden');
515 // show hidden general comment form
515 // show hidden general comment form
516 $('#cb-comment-general-form-placeholder').show();
516 $('#cb-comment-general-form-placeholder').show();
517 } else {
517 } else {
518 var $comment = $inline_comments.find('div.comment:hidden');
518 var $comment = $inline_comments.find('div.comment:hidden');
519 }
519 }
520 $comment.show();
520 $comment.show();
521 }
521 }
522 $node.closest('.comment-inline-form').remove();
522 $node.closest('.comment-inline-form').remove();
523 return false;
523 return false;
524 };
524 };
525
525
526 this.showVersion = function (node) {
526 this.showVersion = function (node) {
527 var $node = $(node);
527 var $node = $(node);
528 var selectedIndex = $node.context.selectedIndex;
528 var selectedIndex = $node.context.selectedIndex;
529 var option = $node.find('option[value="'+ selectedIndex +'"]');
529 var option = $node.find('option[value="'+ selectedIndex +'"]');
530 var zero_option = $node.find('option[value="0"]');
530 var zero_option = $node.find('option[value="0"]');
531 if (!option){
531 if (!option){
532 return;
532 return;
533 }
533 }
534
534
535 // little trick to cheat onchange and allow to display the same version again
535 // little trick to cheat onchange and allow to display the same version again
536 $node.context.selectedIndex = 0;
536 $node.context.selectedIndex = 0;
537 zero_option.text(selectedIndex);
537 zero_option.text(selectedIndex);
538
538
539 var comment_history_id = option.attr('data-comment-history-id');
539 var comment_history_id = option.attr('data-comment-history-id');
540 var comment_id = option.attr('data-comment-id');
540 var comment_id = option.attr('data-comment-id');
541 var historyViewUrl = pyroutes.url(
541 var historyViewUrl = pyroutes.url(
542 'repo_commit_comment_history_view',
542 'repo_commit_comment_history_view',
543 {
543 {
544 'repo_name': templateContext.repo_name,
544 'repo_name': templateContext.repo_name,
545 'commit_id': comment_id,
545 'commit_id': comment_id,
546 'comment_history_id': comment_history_id,
546 'comment_history_id': comment_history_id,
547 }
547 }
548 );
548 );
549 successRenderCommit = function (data) {
549 successRenderCommit = function (data) {
550 SwalNoAnimation.fire({
550 SwalNoAnimation.fire({
551 html: data,
551 html: data,
552 title: '',
552 title: '',
553 });
553 });
554 };
554 };
555 failRenderCommit = function () {
555 failRenderCommit = function () {
556 SwalNoAnimation.fire({
556 SwalNoAnimation.fire({
557 html: 'Error while loading comment',
557 html: 'Error while loading comment',
558 title: '',
558 title: '',
559 });
559 });
560 };
560 };
561 _submitAjaxPOST(
561 _submitAjaxPOST(
562 historyViewUrl, {'csrf_token': CSRF_TOKEN}, successRenderCommit,
562 historyViewUrl, {'csrf_token': CSRF_TOKEN}, successRenderCommit,
563 failRenderCommit
563 failRenderCommit
564 );
564 );
565 };
565 };
566
566
567 this.getLineNumber = function(node) {
567 this.getLineNumber = function(node) {
568 var $node = $(node);
568 var $node = $(node);
569 var lineNo = $node.closest('td').attr('data-line-no');
569 var lineNo = $node.closest('td').attr('data-line-no');
570 if (lineNo === undefined && $node.data('commentInline')){
570 if (lineNo === undefined && $node.data('commentInline')){
571 lineNo = $node.data('commentLineNo')
571 lineNo = $node.data('commentLineNo')
572 }
572 }
573
573
574 return lineNo
574 return lineNo
575 };
575 };
576
576
577 this.scrollToComment = function(node, offset, outdated) {
577 this.scrollToComment = function(node, offset, outdated) {
578 if (offset === undefined) {
578 if (offset === undefined) {
579 offset = 0;
579 offset = 0;
580 }
580 }
581 var outdated = outdated || false;
581 var outdated = outdated || false;
582 var klass = outdated ? 'div.comment-outdated' : 'div.comment-current';
582 var klass = outdated ? 'div.comment-outdated' : 'div.comment-current';
583
583
584 if (!node) {
584 if (!node) {
585 node = $('.comment-selected');
585 node = $('.comment-selected');
586 if (!node.length) {
586 if (!node.length) {
587 node = $('comment-current')
587 node = $('comment-current')
588 }
588 }
589 }
589 }
590
590
591 $wrapper = $(node).closest('div.comment');
591 $wrapper = $(node).closest('div.comment');
592
592
593 // show hidden comment when referenced.
593 // show hidden comment when referenced.
594 if (!$wrapper.is(':visible')){
594 if (!$wrapper.is(':visible')){
595 $wrapper.show();
595 $wrapper.show();
596 }
596 }
597
597
598 $comment = $(node).closest(klass);
598 $comment = $(node).closest(klass);
599 $comments = $(klass);
599 $comments = $(klass);
600
600
601 $('.comment-selected').removeClass('comment-selected');
601 $('.comment-selected').removeClass('comment-selected');
602
602
603 var nextIdx = $(klass).index($comment) + offset;
603 var nextIdx = $(klass).index($comment) + offset;
604 if (nextIdx >= $comments.length) {
604 if (nextIdx >= $comments.length) {
605 nextIdx = 0;
605 nextIdx = 0;
606 }
606 }
607 var $next = $(klass).eq(nextIdx);
607 var $next = $(klass).eq(nextIdx);
608
608
609 var $cb = $next.closest('.cb');
609 var $cb = $next.closest('.cb');
610 $cb.removeClass('cb-collapsed');
610 $cb.removeClass('cb-collapsed');
611
611
612 var $filediffCollapseState = $cb.closest('.filediff').prev();
612 var $filediffCollapseState = $cb.closest('.filediff').prev();
613 $filediffCollapseState.prop('checked', false);
613 $filediffCollapseState.prop('checked', false);
614 $next.addClass('comment-selected');
614 $next.addClass('comment-selected');
615 scrollToElement($next);
615 scrollToElement($next);
616 return false;
616 return false;
617 };
617 };
618
618
619 this.nextComment = function(node) {
619 this.nextComment = function(node) {
620 return self.scrollToComment(node, 1);
620 return self.scrollToComment(node, 1);
621 };
621 };
622
622
623 this.prevComment = function(node) {
623 this.prevComment = function(node) {
624 return self.scrollToComment(node, -1);
624 return self.scrollToComment(node, -1);
625 };
625 };
626
626
627 this.nextOutdatedComment = function(node) {
627 this.nextOutdatedComment = function(node) {
628 return self.scrollToComment(node, 1, true);
628 return self.scrollToComment(node, 1, true);
629 };
629 };
630
630
631 this.prevOutdatedComment = function(node) {
631 this.prevOutdatedComment = function(node) {
632 return self.scrollToComment(node, -1, true);
632 return self.scrollToComment(node, -1, true);
633 };
633 };
634
634
635 this._deleteComment = function(node) {
635 this._deleteComment = function(node) {
636 var $node = $(node);
636 var $node = $(node);
637 var $td = $node.closest('td');
637 var $td = $node.closest('td');
638 var $comment = $node.closest('.comment');
638 var $comment = $node.closest('.comment');
639 var comment_id = $comment.attr('data-comment-id');
639 var comment_id = $comment.attr('data-comment-id');
640 var url = AJAX_COMMENT_DELETE_URL.replace('__COMMENT_ID__', comment_id);
640 var url = AJAX_COMMENT_DELETE_URL.replace('__COMMENT_ID__', comment_id);
641 var postData = {
641 var postData = {
642 'csrf_token': CSRF_TOKEN
642 'csrf_token': CSRF_TOKEN
643 };
643 };
644
644
645 $comment.addClass('comment-deleting');
645 $comment.addClass('comment-deleting');
646 $comment.hide('fast');
646 $comment.hide('fast');
647
647
648 var success = function(response) {
648 var success = function(response) {
649 $comment.remove();
649 $comment.remove();
650 return false;
650 return false;
651 };
651 };
652 var failure = function(jqXHR, textStatus, errorThrown) {
652 var failure = function(jqXHR, textStatus, errorThrown) {
653 var prefix = "Error while deleting this comment.\n"
653 var prefix = "Error while deleting this comment.\n"
654 var message = formatErrorMessage(jqXHR, textStatus, errorThrown, prefix);
654 var message = formatErrorMessage(jqXHR, textStatus, errorThrown, prefix);
655 ajaxErrorSwal(message);
655 ajaxErrorSwal(message);
656
656
657 $comment.show('fast');
657 $comment.show('fast');
658 $comment.removeClass('comment-deleting');
658 $comment.removeClass('comment-deleting');
659 return false;
659 return false;
660 };
660 };
661 ajaxPOST(url, postData, success, failure);
661 ajaxPOST(url, postData, success, failure);
662 }
662 }
663
663
664 this.deleteComment = function(node) {
664 this.deleteComment = function(node) {
665 var $comment = $(node).closest('.comment');
665 var $comment = $(node).closest('.comment');
666 var comment_id = $comment.attr('data-comment-id');
666 var comment_id = $comment.attr('data-comment-id');
667
667
668 SwalNoAnimation.fire({
668 SwalNoAnimation.fire({
669 title: 'Delete this comment?',
669 title: 'Delete this comment?',
670 icon: 'warning',
670 icon: 'warning',
671 showCancelButton: true,
671 showCancelButton: true,
672 confirmButtonText: _gettext('Yes, delete comment #{0}!').format(comment_id),
672 confirmButtonText: _gettext('Yes, delete comment #{0}!').format(comment_id),
673
673
674 }).then(function(result) {
674 }).then(function(result) {
675 if (result.value) {
675 if (result.value) {
676 self._deleteComment(node);
676 self._deleteComment(node);
677 }
677 }
678 })
678 })
679 };
679 };
680
680
681 this.toggleWideMode = function (node) {
681 this.toggleWideMode = function (node) {
682 if ($('#content').hasClass('wrapper')) {
682 if ($('#content').hasClass('wrapper')) {
683 $('#content').removeClass("wrapper");
683 $('#content').removeClass("wrapper");
684 $('#content').addClass("wide-mode-wrapper");
684 $('#content').addClass("wide-mode-wrapper");
685 $(node).addClass('btn-success');
685 $(node).addClass('btn-success');
686 return true
686 return true
687 } else {
687 } else {
688 $('#content').removeClass("wide-mode-wrapper");
688 $('#content').removeClass("wide-mode-wrapper");
689 $('#content').addClass("wrapper");
689 $('#content').addClass("wrapper");
690 $(node).removeClass('btn-success');
690 $(node).removeClass('btn-success');
691 return false
691 return false
692 }
692 }
693
693
694 };
694 };
695
695
696 this.toggleComments = function(node, show) {
696 this.toggleComments = function(node, show) {
697 var $filediff = $(node).closest('.filediff');
697 var $filediff = $(node).closest('.filediff');
698 if (show === true) {
698 if (show === true) {
699 $filediff.removeClass('hide-comments');
699 $filediff.removeClass('hide-comments');
700 } else if (show === false) {
700 } else if (show === false) {
701 $filediff.find('.hide-line-comments').removeClass('hide-line-comments');
701 $filediff.find('.hide-line-comments').removeClass('hide-line-comments');
702 $filediff.addClass('hide-comments');
702 $filediff.addClass('hide-comments');
703 } else {
703 } else {
704 $filediff.find('.hide-line-comments').removeClass('hide-line-comments');
704 $filediff.find('.hide-line-comments').removeClass('hide-line-comments');
705 $filediff.toggleClass('hide-comments');
705 $filediff.toggleClass('hide-comments');
706 }
706 }
707 return false;
707 return false;
708 };
708 };
709
709
710 this.toggleLineComments = function(node) {
710 this.toggleLineComments = function(node) {
711 self.toggleComments(node, true);
711 self.toggleComments(node, true);
712 var $node = $(node);
712 var $node = $(node);
713 // mark outdated comments as visible before the toggle;
713 // mark outdated comments as visible before the toggle;
714 $(node.closest('tr')).find('.comment-outdated').show();
714 $(node.closest('tr')).find('.comment-outdated').show();
715 $node.closest('tr').toggleClass('hide-line-comments');
715 $node.closest('tr').toggleClass('hide-line-comments');
716 };
716 };
717
717
718 this.createCommentForm = function(formElement, lineno, placeholderText, initAutocompleteActions, resolvesCommentId, edit, comment_id){
718 this.createCommentForm = function(formElement, lineno, placeholderText, initAutocompleteActions, resolvesCommentId, edit, comment_id){
719 var pullRequestId = templateContext.pull_request_data.pull_request_id;
719 var pullRequestId = templateContext.pull_request_data.pull_request_id;
720 var commitId = templateContext.commit_data.commit_id;
720 var commitId = templateContext.commit_data.commit_id;
721
721
722 var commentForm = new CommentForm(
722 var commentForm = new CommentForm(
723 formElement, commitId, pullRequestId, lineno, initAutocompleteActions, resolvesCommentId, edit, comment_id);
723 formElement, commitId, pullRequestId, lineno, initAutocompleteActions, resolvesCommentId, edit, comment_id);
724 var cm = commentForm.getCmInstance();
724 var cm = commentForm.getCmInstance();
725
725
726 if (resolvesCommentId){
726 if (resolvesCommentId){
727 var placeholderText = _gettext('Leave a resolution comment, or click resolve button to resolve TODO comment #{0}').format(resolvesCommentId);
727 var placeholderText = _gettext('Leave a resolution comment, or click resolve button to resolve TODO comment #{0}').format(resolvesCommentId);
728 }
728 }
729
729
730 setTimeout(function() {
730 setTimeout(function() {
731 // callbacks
731 // callbacks
732 if (cm !== undefined) {
732 if (cm !== undefined) {
733 commentForm.setPlaceholder(placeholderText);
733 commentForm.setPlaceholder(placeholderText);
734 if (commentForm.isInline()) {
734 if (commentForm.isInline()) {
735 cm.focus();
735 cm.focus();
736 cm.refresh();
736 cm.refresh();
737 }
737 }
738 }
738 }
739 }, 10);
739 }, 10);
740
740
741 // trigger scrolldown to the resolve comment, since it might be away
741 // trigger scrolldown to the resolve comment, since it might be away
742 // from the clicked
742 // from the clicked
743 if (resolvesCommentId){
743 if (resolvesCommentId){
744 var actionNode = $(commentForm.resolvesActionId).offset();
744 var actionNode = $(commentForm.resolvesActionId).offset();
745
745
746 setTimeout(function() {
746 setTimeout(function() {
747 if (actionNode) {
747 if (actionNode) {
748 $('body, html').animate({scrollTop: actionNode.top}, 10);
748 $('body, html').animate({scrollTop: actionNode.top}, 10);
749 }
749 }
750 }, 100);
750 }, 100);
751 }
751 }
752
752
753 // add dropzone support
753 // add dropzone support
754 var insertAttachmentText = function (cm, attachmentName, attachmentStoreUrl, isRendered) {
754 var insertAttachmentText = function (cm, attachmentName, attachmentStoreUrl, isRendered) {
755 var renderer = templateContext.visual.default_renderer;
755 var renderer = templateContext.visual.default_renderer;
756 if (renderer == 'rst') {
756 if (renderer == 'rst') {
757 var attachmentUrl = '`#{0} <{1}>`_'.format(attachmentName, attachmentStoreUrl);
757 var attachmentUrl = '`#{0} <{1}>`_'.format(attachmentName, attachmentStoreUrl);
758 if (isRendered){
758 if (isRendered){
759 attachmentUrl = '\n.. image:: {0}'.format(attachmentStoreUrl);
759 attachmentUrl = '\n.. image:: {0}'.format(attachmentStoreUrl);
760 }
760 }
761 } else if (renderer == 'markdown') {
761 } else if (renderer == 'markdown') {
762 var attachmentUrl = '[{0}]({1})'.format(attachmentName, attachmentStoreUrl);
762 var attachmentUrl = '[{0}]({1})'.format(attachmentName, attachmentStoreUrl);
763 if (isRendered){
763 if (isRendered){
764 attachmentUrl = '!' + attachmentUrl;
764 attachmentUrl = '!' + attachmentUrl;
765 }
765 }
766 } else {
766 } else {
767 var attachmentUrl = '{}'.format(attachmentStoreUrl);
767 var attachmentUrl = '{}'.format(attachmentStoreUrl);
768 }
768 }
769 cm.replaceRange(attachmentUrl+'\n', CodeMirror.Pos(cm.lastLine()));
769 cm.replaceRange(attachmentUrl+'\n', CodeMirror.Pos(cm.lastLine()));
770
770
771 return false;
771 return false;
772 };
772 };
773
773
774 //see: https://www.dropzonejs.com/#configuration
774 //see: https://www.dropzonejs.com/#configuration
775 var storeUrl = pyroutes.url('repo_commit_comment_attachment_upload',
775 var storeUrl = pyroutes.url('repo_commit_comment_attachment_upload',
776 {'repo_name': templateContext.repo_name,
776 {'repo_name': templateContext.repo_name,
777 'commit_id': templateContext.commit_data.commit_id})
777 'commit_id': templateContext.commit_data.commit_id})
778
778
779 var previewTmpl = $(formElement).find('.comment-attachment-uploader-template').get(0);
779 var previewTmpl = $(formElement).find('.comment-attachment-uploader-template').get(0);
780 if (previewTmpl !== undefined){
780 if (previewTmpl !== undefined){
781 var selectLink = $(formElement).find('.pick-attachment').get(0);
781 var selectLink = $(formElement).find('.pick-attachment').get(0);
782 $(formElement).find('.comment-attachment-uploader').dropzone({
782 $(formElement).find('.comment-attachment-uploader').dropzone({
783 url: storeUrl,
783 url: storeUrl,
784 headers: {"X-CSRF-Token": CSRF_TOKEN},
784 headers: {"X-CSRF-Token": CSRF_TOKEN},
785 paramName: function () {
785 paramName: function () {
786 return "attachment"
786 return "attachment"
787 }, // The name that will be used to transfer the file
787 }, // The name that will be used to transfer the file
788 clickable: selectLink,
788 clickable: selectLink,
789 parallelUploads: 1,
789 parallelUploads: 1,
790 maxFiles: 10,
790 maxFiles: 10,
791 maxFilesize: templateContext.attachment_store.max_file_size_mb,
791 maxFilesize: templateContext.attachment_store.max_file_size_mb,
792 uploadMultiple: false,
792 uploadMultiple: false,
793 autoProcessQueue: true, // if false queue will not be processed automatically.
793 autoProcessQueue: true, // if false queue will not be processed automatically.
794 createImageThumbnails: false,
794 createImageThumbnails: false,
795 previewTemplate: previewTmpl.innerHTML,
795 previewTemplate: previewTmpl.innerHTML,
796
796
797 accept: function (file, done) {
797 accept: function (file, done) {
798 done();
798 done();
799 },
799 },
800 init: function () {
800 init: function () {
801
801
802 this.on("sending", function (file, xhr, formData) {
802 this.on("sending", function (file, xhr, formData) {
803 $(formElement).find('.comment-attachment-uploader').find('.dropzone-text').hide();
803 $(formElement).find('.comment-attachment-uploader').find('.dropzone-text').hide();
804 $(formElement).find('.comment-attachment-uploader').find('.dropzone-upload').show();
804 $(formElement).find('.comment-attachment-uploader').find('.dropzone-upload').show();
805 });
805 });
806
806
807 this.on("success", function (file, response) {
807 this.on("success", function (file, response) {
808 $(formElement).find('.comment-attachment-uploader').find('.dropzone-text').show();
808 $(formElement).find('.comment-attachment-uploader').find('.dropzone-text').show();
809 $(formElement).find('.comment-attachment-uploader').find('.dropzone-upload').hide();
809 $(formElement).find('.comment-attachment-uploader').find('.dropzone-upload').hide();
810
810
811 var isRendered = false;
811 var isRendered = false;
812 var ext = file.name.split('.').pop();
812 var ext = file.name.split('.').pop();
813 var imageExts = templateContext.attachment_store.image_ext;
813 var imageExts = templateContext.attachment_store.image_ext;
814 if (imageExts.indexOf(ext) !== -1){
814 if (imageExts.indexOf(ext) !== -1){
815 isRendered = true;
815 isRendered = true;
816 }
816 }
817
817
818 insertAttachmentText(cm, file.name, response.repo_fqn_access_path, isRendered)
818 insertAttachmentText(cm, file.name, response.repo_fqn_access_path, isRendered)
819 });
819 });
820
820
821 this.on("error", function (file, errorMessage, xhr) {
821 this.on("error", function (file, errorMessage, xhr) {
822 $(formElement).find('.comment-attachment-uploader').find('.dropzone-upload').hide();
822 $(formElement).find('.comment-attachment-uploader').find('.dropzone-upload').hide();
823
823
824 var error = null;
824 var error = null;
825
825
826 if (xhr !== undefined){
826 if (xhr !== undefined){
827 var httpStatus = xhr.status + " " + xhr.statusText;
827 var httpStatus = xhr.status + " " + xhr.statusText;
828 if (xhr !== undefined && xhr.status >= 500) {
828 if (xhr !== undefined && xhr.status >= 500) {
829 error = httpStatus;
829 error = httpStatus;
830 }
830 }
831 }
831 }
832
832
833 if (error === null) {
833 if (error === null) {
834 error = errorMessage.error || errorMessage || httpStatus;
834 error = errorMessage.error || errorMessage || httpStatus;
835 }
835 }
836 $(file.previewElement).find('.dz-error-message').html('ERROR: {0}'.format(error));
836 $(file.previewElement).find('.dz-error-message').html('ERROR: {0}'.format(error));
837
837
838 });
838 });
839 }
839 }
840 });
840 });
841 }
841 }
842 return commentForm;
842 return commentForm;
843 };
843 };
844
844
845 this.createGeneralComment = function (lineNo, placeholderText, resolvesCommentId) {
845 this.createGeneralComment = function (lineNo, placeholderText, resolvesCommentId) {
846
846
847 var tmpl = $('#cb-comment-general-form-template').html();
847 var tmpl = $('#cb-comment-general-form-template').html();
848 tmpl = tmpl.format(null, 'general');
848 tmpl = tmpl.format(null, 'general');
849 var $form = $(tmpl);
849 var $form = $(tmpl);
850
850
851 var $formPlaceholder = $('#cb-comment-general-form-placeholder');
851 var $formPlaceholder = $('#cb-comment-general-form-placeholder');
852 var curForm = $formPlaceholder.find('form');
852 var curForm = $formPlaceholder.find('form');
853 if (curForm){
853 if (curForm){
854 curForm.remove();
854 curForm.remove();
855 }
855 }
856 $formPlaceholder.append($form);
856 $formPlaceholder.append($form);
857
857
858 var _form = $($form[0]);
858 var _form = $($form[0]);
859 var autocompleteActions = ['approve', 'reject', 'as_note', 'as_todo'];
859 var autocompleteActions = ['approve', 'reject', 'as_note', 'as_todo'];
860 var edit = false;
860 var edit = false;
861 var comment_id = null;
861 var comment_id = null;
862 var commentForm = this.createCommentForm(
862 var commentForm = this.createCommentForm(
863 _form, lineNo, placeholderText, autocompleteActions, resolvesCommentId, edit, comment_id);
863 _form, lineNo, placeholderText, autocompleteActions, resolvesCommentId, edit, comment_id);
864 commentForm.initStatusChangeSelector();
864 commentForm.initStatusChangeSelector();
865
865
866 return commentForm;
866 return commentForm;
867 };
867 };
868 this.editComment = function(node) {
868 this.editComment = function(node) {
869 var $node = $(node);
869 var $node = $(node);
870 var $comment = $(node).closest('.comment');
870 var $comment = $(node).closest('.comment');
871 var comment_id = $comment.attr('data-comment-id');
871 var comment_id = $comment.attr('data-comment-id');
872 var $form = null
872 var $form = null
873
873
874 var $comments = $node.closest('div.inline-comments');
874 var $comments = $node.closest('div.inline-comments');
875 var $general_comments = null;
875 var $general_comments = null;
876 var lineno = null;
876 var lineno = null;
877
877
878 if($comments.length){
878 if($comments.length){
879 // inline comments setup
879 // inline comments setup
880 $form = $comments.find('.comment-inline-form');
880 $form = $comments.find('.comment-inline-form');
881 lineno = self.getLineNumber(node)
881 lineno = self.getLineNumber(node)
882 }
882 }
883 else{
883 else{
884 // general comments setup
884 // general comments setup
885 $comments = $('#comments');
885 $comments = $('#comments');
886 $form = $comments.find('.comment-inline-form');
886 $form = $comments.find('.comment-inline-form');
887 lineno = $comment[0].id
887 lineno = $comment[0].id
888 $('#cb-comment-general-form-placeholder').hide();
888 $('#cb-comment-general-form-placeholder').hide();
889 }
889 }
890
890
891 this.edit = true;
891 this.edit = true;
892
892
893 if (!$form.length) {
893 if (!$form.length) {
894
894
895 var $filediff = $node.closest('.filediff');
895 var $filediff = $node.closest('.filediff');
896 $filediff.removeClass('hide-comments');
896 $filediff.removeClass('hide-comments');
897 var f_path = $filediff.attr('data-f-path');
897 var f_path = $filediff.attr('data-f-path');
898
898
899 // create a new HTML from template
899 // create a new HTML from template
900
900
901 var tmpl = $('#cb-comment-inline-form-template').html();
901 var tmpl = $('#cb-comment-inline-form-template').html();
902 tmpl = tmpl.format(escapeHtml(f_path), lineno);
902 tmpl = tmpl.format(escapeHtml(f_path), lineno);
903 $form = $(tmpl);
903 $form = $(tmpl);
904 $comment.after($form)
904 $comment.after($form)
905
905
906 var _form = $($form[0]).find('form');
906 var _form = $($form[0]).find('form');
907 var autocompleteActions = ['as_note',];
907 var autocompleteActions = ['as_note',];
908 var commentForm = this.createCommentForm(
908 var commentForm = this.createCommentForm(
909 _form, lineno, '', autocompleteActions, resolvesCommentId,
909 _form, lineno, '', autocompleteActions, resolvesCommentId,
910 this.edit, comment_id);
910 this.edit, comment_id);
911 var old_comment_text_binary = $comment.attr('data-comment-text');
911 var old_comment_text_binary = $comment.attr('data-comment-text');
912 var old_comment_text = b64DecodeUnicode(old_comment_text_binary);
912 var old_comment_text = b64DecodeUnicode(old_comment_text_binary);
913 commentForm.cm.setValue(old_comment_text);
913 commentForm.cm.setValue(old_comment_text);
914 $comment.hide();
914 $comment.hide();
915
915
916 $.Topic('/ui/plugins/code/comment_form_built').prepareOrPublish({
916 $.Topic('/ui/plugins/code/comment_form_built').prepareOrPublish({
917 form: _form,
917 form: _form,
918 parent: $comments,
918 parent: $comments,
919 lineno: lineno,
919 lineno: lineno,
920 f_path: f_path}
920 f_path: f_path}
921 );
921 );
922 // set a CUSTOM submit handler for inline comments.
922 // set a CUSTOM submit handler for inline comments.
923 commentForm.setHandleFormSubmit(function(o) {
923 commentForm.setHandleFormSubmit(function(o) {
924 var text = commentForm.cm.getValue();
924 var text = commentForm.cm.getValue();
925 var commentType = commentForm.getCommentType();
925 var commentType = commentForm.getCommentType();
926 var resolvesCommentId = commentForm.getResolvesId();
926 var resolvesCommentId = commentForm.getResolvesId();
927
927
928 if (text === "") {
928 if (text === "") {
929 return;
929 return;
930 }
930 }
931 if (old_comment_text == text) {
931 if (old_comment_text == text) {
932 SwalNoAnimation.fire({
932 SwalNoAnimation.fire({
933 title: 'Error',
933 title: 'Unable to edit comment',
934 html: _gettext('Comment body should be changed'),
934 html: _gettext('Comment body was not changed.'),
935 });
935 });
936 return;
936 return;
937 }
937 }
938 var excludeCancelBtn = false;
938 var excludeCancelBtn = false;
939 var submitEvent = true;
939 var submitEvent = true;
940 commentForm.setActionButtonsDisabled(true, excludeCancelBtn, submitEvent);
940 commentForm.setActionButtonsDisabled(true, excludeCancelBtn, submitEvent);
941 commentForm.cm.setOption("readOnly", true);
941 commentForm.cm.setOption("readOnly", true);
942 var dropDown = $('#comment_history_for_comment_'+comment_id);
942 var dropDown = $('#comment_history_for_comment_'+comment_id);
943
943
944 var version = dropDown.children().last().val()
944 var version = dropDown.children().last().val()
945 if(!version){
945 if(!version){
946 version = 0;
946 version = 0;
947 }
947 }
948 var postData = {
948 var postData = {
949 'text': text,
949 'text': text,
950 'f_path': f_path,
950 'f_path': f_path,
951 'line': lineno,
951 'line': lineno,
952 'comment_type': commentType,
952 'comment_type': commentType,
953 'csrf_token': CSRF_TOKEN,
953 'csrf_token': CSRF_TOKEN,
954 'version': version,
954 'version': version,
955 };
955 };
956
956
957 var submitSuccessCallback = function(json_data) {
957 var submitSuccessCallback = function(json_data) {
958 $form.remove();
958 $form.remove();
959 $comment.show();
959 $comment.show();
960 var postData = {
960 var postData = {
961 'text': text,
961 'text': text,
962 'renderer': $comment.attr('data-comment-renderer'),
962 'renderer': $comment.attr('data-comment-renderer'),
963 'csrf_token': CSRF_TOKEN
963 'csrf_token': CSRF_TOKEN
964 };
964 };
965
965
966 var updateCommentVersionDropDown = function () {
966 var updateCommentVersionDropDown = function () {
967 var dropDown = $('#comment_history_for_comment_'+comment_id);
967 var dropDown = $('#comment_history_for_comment_'+comment_id);
968 $comment.attr('data-comment-text', btoa(text));
968 $comment.attr('data-comment-text', btoa(text));
969 var version = json_data['comment_version']
969 var version = json_data['comment_version']
970 var option = new Option(version, version);
970 var option = new Option(version, version);
971 var $option = $(option);
971 var $option = $(option);
972 $option.attr('data-comment-history-id', json_data['comment_history_id']);
972 $option.attr('data-comment-history-id', json_data['comment_history_id']);
973 $option.attr('data-comment-id', json_data['comment_id']);
973 $option.attr('data-comment-id', json_data['comment_id']);
974 dropDown.append(option);
974 dropDown.append(option);
975 dropDown.parent().show();
975 dropDown.parent().show();
976 }
976 }
977 updateCommentVersionDropDown();
977 updateCommentVersionDropDown();
978 // by default we reset state of comment preserving the text
978 // by default we reset state of comment preserving the text
979 var failRenderCommit = function(jqXHR, textStatus, errorThrown) {
979 var failRenderCommit = function(jqXHR, textStatus, errorThrown) {
980 var prefix = "Error while editing of comment.\n"
980 var prefix = "Error while editing of comment.\n"
981 var message = formatErrorMessage(jqXHR, textStatus, errorThrown, prefix);
981 var message = formatErrorMessage(jqXHR, textStatus, errorThrown, prefix);
982 ajaxErrorSwal(message);
982 ajaxErrorSwal(message);
983
983
984 };
984 };
985 var successRenderCommit = function(o){
985 var successRenderCommit = function(o){
986 $comment.show();
986 $comment.show();
987 $comment[0].lastElementChild.innerHTML = o;
987 $comment[0].lastElementChild.innerHTML = o;
988 }
988 }
989 var previewUrl = pyroutes.url('repo_commit_comment_preview',
989 var previewUrl = pyroutes.url('repo_commit_comment_preview',
990 {'repo_name': templateContext.repo_name,
990 {'repo_name': templateContext.repo_name,
991 'commit_id': templateContext.commit_data.commit_id});
991 'commit_id': templateContext.commit_data.commit_id});
992
992
993 _submitAjaxPOST(
993 _submitAjaxPOST(
994 previewUrl, postData, successRenderCommit,
994 previewUrl, postData, successRenderCommit,
995 failRenderCommit
995 failRenderCommit
996 );
996 );
997
997
998 try {
998 try {
999 var html = json_data.rendered_text;
999 var html = json_data.rendered_text;
1000 var lineno = json_data.line_no;
1000 var lineno = json_data.line_no;
1001 var target_id = json_data.target_id;
1001 var target_id = json_data.target_id;
1002
1002
1003 $comments.find('.cb-comment-add-button').before(html);
1003 $comments.find('.cb-comment-add-button').before(html);
1004
1004
1005 //mark visually which comment was resolved
1005 //mark visually which comment was resolved
1006 if (resolvesCommentId) {
1006 if (resolvesCommentId) {
1007 commentForm.markCommentResolved(resolvesCommentId);
1007 commentForm.markCommentResolved(resolvesCommentId);
1008 }
1008 }
1009
1009
1010 // run global callback on submit
1010 // run global callback on submit
1011 commentForm.globalSubmitSuccessCallback();
1011 commentForm.globalSubmitSuccessCallback();
1012
1012
1013 } catch (e) {
1013 } catch (e) {
1014 console.error(e);
1014 console.error(e);
1015 }
1015 }
1016
1016
1017 // re trigger the linkification of next/prev navigation
1017 // re trigger the linkification of next/prev navigation
1018 linkifyComments($('.inline-comment-injected'));
1018 linkifyComments($('.inline-comment-injected'));
1019 timeagoActivate();
1019 timeagoActivate();
1020 tooltipActivate();
1020 tooltipActivate();
1021
1021
1022 if (window.updateSticky !== undefined) {
1022 if (window.updateSticky !== undefined) {
1023 // potentially our comments change the active window size, so we
1023 // potentially our comments change the active window size, so we
1024 // notify sticky elements
1024 // notify sticky elements
1025 updateSticky()
1025 updateSticky()
1026 }
1026 }
1027
1027
1028 commentForm.setActionButtonsDisabled(false);
1028 commentForm.setActionButtonsDisabled(false);
1029
1029
1030 };
1030 };
1031 var submitFailCallback = function(jqXHR, textStatus, errorThrown) {
1031 var submitFailCallback = function(jqXHR, textStatus, errorThrown) {
1032 var prefix = "Error while editing comment.\n"
1032 var prefix = "Error while editing comment.\n"
1033 var message = formatErrorMessage(jqXHR, textStatus, errorThrown, prefix);
1033 var message = formatErrorMessage(jqXHR, textStatus, errorThrown, prefix);
1034 ajaxErrorSwal(message);
1034 ajaxErrorSwal(message);
1035 commentForm.resetCommentFormState(text)
1035 commentForm.resetCommentFormState(text)
1036 };
1036 };
1037 commentForm.submitAjaxPOST(
1037 commentForm.submitAjaxPOST(
1038 commentForm.submitUrl, postData, submitSuccessCallback, submitFailCallback);
1038 commentForm.submitUrl, postData, submitSuccessCallback, submitFailCallback);
1039 });
1039 });
1040 }
1040 }
1041
1041
1042 $form.addClass('comment-inline-form-open');
1042 $form.addClass('comment-inline-form-open');
1043 };
1043 };
1044 this.createComment = function(node, resolutionComment) {
1044 this.createComment = function(node, resolutionComment) {
1045 var resolvesCommentId = resolutionComment || null;
1045 var resolvesCommentId = resolutionComment || null;
1046 var $node = $(node);
1046 var $node = $(node);
1047 var $td = $node.closest('td');
1047 var $td = $node.closest('td');
1048 var $form = $td.find('.comment-inline-form');
1048 var $form = $td.find('.comment-inline-form');
1049 this.edit = false;
1049 this.edit = false;
1050
1050
1051 if (!$form.length) {
1051 if (!$form.length) {
1052
1052
1053 var $filediff = $node.closest('.filediff');
1053 var $filediff = $node.closest('.filediff');
1054 $filediff.removeClass('hide-comments');
1054 $filediff.removeClass('hide-comments');
1055 var f_path = $filediff.attr('data-f-path');
1055 var f_path = $filediff.attr('data-f-path');
1056 var lineno = self.getLineNumber(node);
1056 var lineno = self.getLineNumber(node);
1057 // create a new HTML from template
1057 // create a new HTML from template
1058 var tmpl = $('#cb-comment-inline-form-template').html();
1058 var tmpl = $('#cb-comment-inline-form-template').html();
1059 tmpl = tmpl.format(escapeHtml(f_path), lineno);
1059 tmpl = tmpl.format(escapeHtml(f_path), lineno);
1060 $form = $(tmpl);
1060 $form = $(tmpl);
1061
1061
1062 var $comments = $td.find('.inline-comments');
1062 var $comments = $td.find('.inline-comments');
1063 if (!$comments.length) {
1063 if (!$comments.length) {
1064 $comments = $(
1064 $comments = $(
1065 $('#cb-comments-inline-container-template').html());
1065 $('#cb-comments-inline-container-template').html());
1066 $td.append($comments);
1066 $td.append($comments);
1067 }
1067 }
1068
1068
1069 $td.find('.cb-comment-add-button').before($form);
1069 $td.find('.cb-comment-add-button').before($form);
1070
1070
1071 var placeholderText = _gettext('Leave a comment on line {0}.').format(lineno);
1071 var placeholderText = _gettext('Leave a comment on line {0}.').format(lineno);
1072 var _form = $($form[0]).find('form');
1072 var _form = $($form[0]).find('form');
1073 var autocompleteActions = ['as_note', 'as_todo'];
1073 var autocompleteActions = ['as_note', 'as_todo'];
1074 var comment_id=null;
1074 var comment_id=null;
1075 var commentForm = this.createCommentForm(
1075 var commentForm = this.createCommentForm(
1076 _form, lineno, placeholderText, autocompleteActions, resolvesCommentId, this.edit, comment_id);
1076 _form, lineno, placeholderText, autocompleteActions, resolvesCommentId, this.edit, comment_id);
1077
1077
1078 $.Topic('/ui/plugins/code/comment_form_built').prepareOrPublish({
1078 $.Topic('/ui/plugins/code/comment_form_built').prepareOrPublish({
1079 form: _form,
1079 form: _form,
1080 parent: $td[0],
1080 parent: $td[0],
1081 lineno: lineno,
1081 lineno: lineno,
1082 f_path: f_path}
1082 f_path: f_path}
1083 );
1083 );
1084
1084
1085 // set a CUSTOM submit handler for inline comments.
1085 // set a CUSTOM submit handler for inline comments.
1086 commentForm.setHandleFormSubmit(function(o) {
1086 commentForm.setHandleFormSubmit(function(o) {
1087 var text = commentForm.cm.getValue();
1087 var text = commentForm.cm.getValue();
1088 var commentType = commentForm.getCommentType();
1088 var commentType = commentForm.getCommentType();
1089 var resolvesCommentId = commentForm.getResolvesId();
1089 var resolvesCommentId = commentForm.getResolvesId();
1090
1090
1091 if (text === "") {
1091 if (text === "") {
1092 return;
1092 return;
1093 }
1093 }
1094
1094
1095 if (lineno === undefined) {
1095 if (lineno === undefined) {
1096 alert('missing line !');
1096 alert('missing line !');
1097 return;
1097 return;
1098 }
1098 }
1099 if (f_path === undefined) {
1099 if (f_path === undefined) {
1100 alert('missing file path !');
1100 alert('missing file path !');
1101 return;
1101 return;
1102 }
1102 }
1103
1103
1104 var excludeCancelBtn = false;
1104 var excludeCancelBtn = false;
1105 var submitEvent = true;
1105 var submitEvent = true;
1106 commentForm.setActionButtonsDisabled(true, excludeCancelBtn, submitEvent);
1106 commentForm.setActionButtonsDisabled(true, excludeCancelBtn, submitEvent);
1107 commentForm.cm.setOption("readOnly", true);
1107 commentForm.cm.setOption("readOnly", true);
1108 var postData = {
1108 var postData = {
1109 'text': text,
1109 'text': text,
1110 'f_path': f_path,
1110 'f_path': f_path,
1111 'line': lineno,
1111 'line': lineno,
1112 'comment_type': commentType,
1112 'comment_type': commentType,
1113 'csrf_token': CSRF_TOKEN
1113 'csrf_token': CSRF_TOKEN
1114 };
1114 };
1115 if (resolvesCommentId){
1115 if (resolvesCommentId){
1116 postData['resolves_comment_id'] = resolvesCommentId;
1116 postData['resolves_comment_id'] = resolvesCommentId;
1117 }
1117 }
1118
1118
1119 var submitSuccessCallback = function(json_data) {
1119 var submitSuccessCallback = function(json_data) {
1120 $form.remove();
1120 $form.remove();
1121 try {
1121 try {
1122 var html = json_data.rendered_text;
1122 var html = json_data.rendered_text;
1123 var lineno = json_data.line_no;
1123 var lineno = json_data.line_no;
1124 var target_id = json_data.target_id;
1124 var target_id = json_data.target_id;
1125
1125
1126 $comments.find('.cb-comment-add-button').before(html);
1126 $comments.find('.cb-comment-add-button').before(html);
1127
1127
1128 //mark visually which comment was resolved
1128 //mark visually which comment was resolved
1129 if (resolvesCommentId) {
1129 if (resolvesCommentId) {
1130 commentForm.markCommentResolved(resolvesCommentId);
1130 commentForm.markCommentResolved(resolvesCommentId);
1131 }
1131 }
1132
1132
1133 // run global callback on submit
1133 // run global callback on submit
1134 commentForm.globalSubmitSuccessCallback();
1134 commentForm.globalSubmitSuccessCallback();
1135
1135
1136 } catch (e) {
1136 } catch (e) {
1137 console.error(e);
1137 console.error(e);
1138 }
1138 }
1139
1139
1140 // re trigger the linkification of next/prev navigation
1140 // re trigger the linkification of next/prev navigation
1141 linkifyComments($('.inline-comment-injected'));
1141 linkifyComments($('.inline-comment-injected'));
1142 timeagoActivate();
1142 timeagoActivate();
1143 tooltipActivate();
1143 tooltipActivate();
1144
1144
1145 if (window.updateSticky !== undefined) {
1145 if (window.updateSticky !== undefined) {
1146 // potentially our comments change the active window size, so we
1146 // potentially our comments change the active window size, so we
1147 // notify sticky elements
1147 // notify sticky elements
1148 updateSticky()
1148 updateSticky()
1149 }
1149 }
1150
1150
1151 commentForm.setActionButtonsDisabled(false);
1151 commentForm.setActionButtonsDisabled(false);
1152
1152
1153 };
1153 };
1154 var submitFailCallback = function(jqXHR, textStatus, errorThrown) {
1154 var submitFailCallback = function(jqXHR, textStatus, errorThrown) {
1155 var prefix = "Error while submitting comment.\n"
1155 var prefix = "Error while submitting comment.\n"
1156 var message = formatErrorMessage(jqXHR, textStatus, errorThrown, prefix);
1156 var message = formatErrorMessage(jqXHR, textStatus, errorThrown, prefix);
1157 ajaxErrorSwal(message);
1157 ajaxErrorSwal(message);
1158 commentForm.resetCommentFormState(text)
1158 commentForm.resetCommentFormState(text)
1159 };
1159 };
1160 commentForm.submitAjaxPOST(
1160 commentForm.submitAjaxPOST(
1161 commentForm.submitUrl, postData, submitSuccessCallback, submitFailCallback);
1161 commentForm.submitUrl, postData, submitSuccessCallback, submitFailCallback);
1162 });
1162 });
1163 }
1163 }
1164
1164
1165 $form.addClass('comment-inline-form-open');
1165 $form.addClass('comment-inline-form-open');
1166 };
1166 };
1167
1167
1168 this.createResolutionComment = function(commentId){
1168 this.createResolutionComment = function(commentId){
1169 // hide the trigger text
1169 // hide the trigger text
1170 $('#resolve-comment-{0}'.format(commentId)).hide();
1170 $('#resolve-comment-{0}'.format(commentId)).hide();
1171
1171
1172 var comment = $('#comment-'+commentId);
1172 var comment = $('#comment-'+commentId);
1173 var commentData = comment.data();
1173 var commentData = comment.data();
1174 if (commentData.commentInline) {
1174 if (commentData.commentInline) {
1175 this.createComment(comment, commentId)
1175 this.createComment(comment, commentId)
1176 } else {
1176 } else {
1177 Rhodecode.comments.createGeneralComment('general', "$placeholder", commentId)
1177 Rhodecode.comments.createGeneralComment('general', "$placeholder", commentId)
1178 }
1178 }
1179
1179
1180 return false;
1180 return false;
1181 };
1181 };
1182
1182
1183 this.submitResolution = function(commentId){
1183 this.submitResolution = function(commentId){
1184 var form = $('#resolve_comment_{0}'.format(commentId)).closest('form');
1184 var form = $('#resolve_comment_{0}'.format(commentId)).closest('form');
1185 var commentForm = form.get(0).CommentForm;
1185 var commentForm = form.get(0).CommentForm;
1186
1186
1187 var cm = commentForm.getCmInstance();
1187 var cm = commentForm.getCmInstance();
1188 var renderer = templateContext.visual.default_renderer;
1188 var renderer = templateContext.visual.default_renderer;
1189 if (renderer == 'rst'){
1189 if (renderer == 'rst'){
1190 var commentUrl = '`#{0} <{1}#comment-{0}>`_'.format(commentId, commentForm.selfUrl);
1190 var commentUrl = '`#{0} <{1}#comment-{0}>`_'.format(commentId, commentForm.selfUrl);
1191 } else if (renderer == 'markdown') {
1191 } else if (renderer == 'markdown') {
1192 var commentUrl = '[#{0}]({1}#comment-{0})'.format(commentId, commentForm.selfUrl);
1192 var commentUrl = '[#{0}]({1}#comment-{0})'.format(commentId, commentForm.selfUrl);
1193 } else {
1193 } else {
1194 var commentUrl = '{1}#comment-{0}'.format(commentId, commentForm.selfUrl);
1194 var commentUrl = '{1}#comment-{0}'.format(commentId, commentForm.selfUrl);
1195 }
1195 }
1196
1196
1197 cm.setValue(_gettext('TODO from comment {0} was fixed.').format(commentUrl));
1197 cm.setValue(_gettext('TODO from comment {0} was fixed.').format(commentUrl));
1198 form.submit();
1198 form.submit();
1199 return false;
1199 return false;
1200 };
1200 };
1201
1201
1202 };
1202 };
General Comments 0
You need to be logged in to leave comments. Login now