##// END OF EJS Templates
js: cleanup linkifyComments function
marcink -
r1329:d188249b default
parent child Browse files
Show More
@@ -1,791 +1,774 b''
1 // # Copyright (C) 2010-2017 RhodeCode GmbH
1 // # Copyright (C) 2010-2017 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 /* TODO: marcink: remove this - it should no longer needed */
29 var firstCommentId = null;
30 for (var i = 0; i < comments.length; i++) {
30 if (comments) {
31 var comment_id = $(comments[i]).data('comment-id');
31 firstCommentId = $(comments[0]).data('comment-id');
32 var prev_comment_id = $(comments[i - 1]).data('comment-id');
33 var next_comment_id = $(comments[i + 1]).data('comment-id');
34
35 // place next/prev links
36 if (prev_comment_id) {
37 $('#prev_c_' + comment_id).show();
38 $('#prev_c_' + comment_id + " a.arrow_comment_link").attr(
39 'href', '#comment-' + prev_comment_id).removeClass('disabled');
40 }
41 if (next_comment_id) {
42 $('#next_c_' + comment_id).show();
43 $('#next_c_' + comment_id + " a.arrow_comment_link").attr(
44 'href', '#comment-' + next_comment_id).removeClass('disabled');
45 }
46 /* TODO(marcink): end removal here */
47
48 // place a first link to the total counter
49 if (i === 0) {
50 $('#inline-comments-counter').attr('href', '#comment-' + comment_id);
51 }
52 }
32 }
53
33
34 if (firstCommentId){
35 $('#inline-comments-counter').attr('href', '#comment-' + firstCommentId);
36 }
54 };
37 };
55
38
56 var bindToggleButtons = function() {
39 var bindToggleButtons = function() {
57 $('.comment-toggle').on('click', function() {
40 $('.comment-toggle').on('click', function() {
58 $(this).parent().nextUntil('tr.line').toggle('inline-comments');
41 $(this).parent().nextUntil('tr.line').toggle('inline-comments');
59 });
42 });
60 };
43 };
61
44
62 /* Comment form for main and inline comments */
45 /* Comment form for main and inline comments */
63
46
64 (function(mod) {
47 (function(mod) {
65 if (typeof exports == "object" && typeof module == "object") // CommonJS
48 if (typeof exports == "object" && typeof module == "object") // CommonJS
66 module.exports = mod();
49 module.exports = mod();
67 else // Plain browser env
50 else // Plain browser env
68 (this || window).CommentForm = mod();
51 (this || window).CommentForm = mod();
69
52
70 })(function() {
53 })(function() {
71 "use strict";
54 "use strict";
72
55
73 function CommentForm(formElement, commitId, pullRequestId, lineNo, initAutocompleteActions, resolvesCommentId) {
56 function CommentForm(formElement, commitId, pullRequestId, lineNo, initAutocompleteActions, resolvesCommentId) {
74 if (!(this instanceof CommentForm)) {
57 if (!(this instanceof CommentForm)) {
75 return new CommentForm(formElement, commitId, pullRequestId, lineNo, initAutocompleteActions, resolvesCommentId);
58 return new CommentForm(formElement, commitId, pullRequestId, lineNo, initAutocompleteActions, resolvesCommentId);
76 }
59 }
77
60
78 // bind the element instance to our Form
61 // bind the element instance to our Form
79 $(formElement).get(0).CommentForm = this;
62 $(formElement).get(0).CommentForm = this;
80
63
81 this.withLineNo = function(selector) {
64 this.withLineNo = function(selector) {
82 var lineNo = this.lineNo;
65 var lineNo = this.lineNo;
83 if (lineNo === undefined) {
66 if (lineNo === undefined) {
84 return selector
67 return selector
85 } else {
68 } else {
86 return selector + '_' + lineNo;
69 return selector + '_' + lineNo;
87 }
70 }
88 };
71 };
89
72
90 this.commitId = commitId;
73 this.commitId = commitId;
91 this.pullRequestId = pullRequestId;
74 this.pullRequestId = pullRequestId;
92 this.lineNo = lineNo;
75 this.lineNo = lineNo;
93 this.initAutocompleteActions = initAutocompleteActions;
76 this.initAutocompleteActions = initAutocompleteActions;
94
77
95 this.previewButton = this.withLineNo('#preview-btn');
78 this.previewButton = this.withLineNo('#preview-btn');
96 this.previewContainer = this.withLineNo('#preview-container');
79 this.previewContainer = this.withLineNo('#preview-container');
97
80
98 this.previewBoxSelector = this.withLineNo('#preview-box');
81 this.previewBoxSelector = this.withLineNo('#preview-box');
99
82
100 this.editButton = this.withLineNo('#edit-btn');
83 this.editButton = this.withLineNo('#edit-btn');
101 this.editContainer = this.withLineNo('#edit-container');
84 this.editContainer = this.withLineNo('#edit-container');
102 this.cancelButton = this.withLineNo('#cancel-btn');
85 this.cancelButton = this.withLineNo('#cancel-btn');
103 this.commentType = this.withLineNo('#comment_type');
86 this.commentType = this.withLineNo('#comment_type');
104
87
105 this.resolvesId = null;
88 this.resolvesId = null;
106 this.resolvesActionId = null;
89 this.resolvesActionId = null;
107
90
108 this.cmBox = this.withLineNo('#text');
91 this.cmBox = this.withLineNo('#text');
109 this.cm = initCommentBoxCodeMirror(this.cmBox, this.initAutocompleteActions);
92 this.cm = initCommentBoxCodeMirror(this.cmBox, this.initAutocompleteActions);
110
93
111 this.statusChange = this.withLineNo('#change_status');
94 this.statusChange = this.withLineNo('#change_status');
112
95
113 this.submitForm = formElement;
96 this.submitForm = formElement;
114 this.submitButton = $(this.submitForm).find('input[type="submit"]');
97 this.submitButton = $(this.submitForm).find('input[type="submit"]');
115 this.submitButtonText = this.submitButton.val();
98 this.submitButtonText = this.submitButton.val();
116
99
117 this.previewUrl = pyroutes.url('changeset_comment_preview',
100 this.previewUrl = pyroutes.url('changeset_comment_preview',
118 {'repo_name': templateContext.repo_name});
101 {'repo_name': templateContext.repo_name});
119
102
120 if (resolvesCommentId){
103 if (resolvesCommentId){
121 this.resolvesId = '#resolve_comment_{0}'.format(resolvesCommentId);
104 this.resolvesId = '#resolve_comment_{0}'.format(resolvesCommentId);
122 this.resolvesActionId = '#resolve_comment_action_{0}'.format(resolvesCommentId);
105 this.resolvesActionId = '#resolve_comment_action_{0}'.format(resolvesCommentId);
123 $(this.commentType).prop('disabled', true);
106 $(this.commentType).prop('disabled', true);
124 $(this.commentType).addClass('disabled');
107 $(this.commentType).addClass('disabled');
125
108
126 // disable select
109 // disable select
127 setTimeout(function() {
110 setTimeout(function() {
128 $(self.statusChange).select2('readonly', true);
111 $(self.statusChange).select2('readonly', true);
129 }, 10);
112 }, 10);
130
113
131 var resolvedInfo = (
114 var resolvedInfo = (
132 '<li class="">' +
115 '<li class="">' +
133 '<input type="hidden" id="resolve_comment_{0}" name="resolve_comment_{0}" value="{0}">' +
116 '<input type="hidden" id="resolve_comment_{0}" name="resolve_comment_{0}" value="{0}">' +
134 '<button id="resolve_comment_action_{0}" class="resolve-text btn btn-sm" onclick="return Rhodecode.comments.submitResolution({0})">{1} #{0}</button>' +
117 '<button id="resolve_comment_action_{0}" class="resolve-text btn btn-sm" onclick="return Rhodecode.comments.submitResolution({0})">{1} #{0}</button>' +
135 '</li>'
118 '</li>'
136 ).format(resolvesCommentId, _gettext('resolve comment'));
119 ).format(resolvesCommentId, _gettext('resolve comment'));
137 $(resolvedInfo).insertAfter($(this.commentType).parent());
120 $(resolvedInfo).insertAfter($(this.commentType).parent());
138 }
121 }
139
122
140 // based on commitId, or pullRequestId decide where do we submit
123 // based on commitId, or pullRequestId decide where do we submit
141 // out data
124 // out data
142 if (this.commitId){
125 if (this.commitId){
143 this.submitUrl = pyroutes.url('changeset_comment',
126 this.submitUrl = pyroutes.url('changeset_comment',
144 {'repo_name': templateContext.repo_name,
127 {'repo_name': templateContext.repo_name,
145 'revision': this.commitId});
128 'revision': this.commitId});
146 this.selfUrl = pyroutes.url('changeset_home',
129 this.selfUrl = pyroutes.url('changeset_home',
147 {'repo_name': templateContext.repo_name,
130 {'repo_name': templateContext.repo_name,
148 'revision': this.commitId});
131 'revision': this.commitId});
149
132
150 } else if (this.pullRequestId) {
133 } else if (this.pullRequestId) {
151 this.submitUrl = pyroutes.url('pullrequest_comment',
134 this.submitUrl = pyroutes.url('pullrequest_comment',
152 {'repo_name': templateContext.repo_name,
135 {'repo_name': templateContext.repo_name,
153 'pull_request_id': this.pullRequestId});
136 'pull_request_id': this.pullRequestId});
154 this.selfUrl = pyroutes.url('pullrequest_show',
137 this.selfUrl = pyroutes.url('pullrequest_show',
155 {'repo_name': templateContext.repo_name,
138 {'repo_name': templateContext.repo_name,
156 'pull_request_id': this.pullRequestId});
139 'pull_request_id': this.pullRequestId});
157
140
158 } else {
141 } else {
159 throw new Error(
142 throw new Error(
160 'CommentForm requires pullRequestId, or commitId to be specified.')
143 'CommentForm requires pullRequestId, or commitId to be specified.')
161 }
144 }
162
145
163 // FUNCTIONS and helpers
146 // FUNCTIONS and helpers
164 var self = this;
147 var self = this;
165
148
166 this.isInline = function(){
149 this.isInline = function(){
167 return this.lineNo && this.lineNo != 'general';
150 return this.lineNo && this.lineNo != 'general';
168 };
151 };
169
152
170 this.getCmInstance = function(){
153 this.getCmInstance = function(){
171 return this.cm
154 return this.cm
172 };
155 };
173
156
174 this.setPlaceholder = function(placeholder) {
157 this.setPlaceholder = function(placeholder) {
175 var cm = this.getCmInstance();
158 var cm = this.getCmInstance();
176 if (cm){
159 if (cm){
177 cm.setOption('placeholder', placeholder);
160 cm.setOption('placeholder', placeholder);
178 }
161 }
179 };
162 };
180
163
181 this.getCommentStatus = function() {
164 this.getCommentStatus = function() {
182 return $(this.submitForm).find(this.statusChange).val();
165 return $(this.submitForm).find(this.statusChange).val();
183 };
166 };
184 this.getCommentType = function() {
167 this.getCommentType = function() {
185 return $(this.submitForm).find(this.commentType).val();
168 return $(this.submitForm).find(this.commentType).val();
186 };
169 };
187
170
188 this.getResolvesId = function() {
171 this.getResolvesId = function() {
189 return $(this.submitForm).find(this.resolvesId).val() || null;
172 return $(this.submitForm).find(this.resolvesId).val() || null;
190 };
173 };
191 this.markCommentResolved = function(resolvedCommentId){
174 this.markCommentResolved = function(resolvedCommentId){
192 $('#comment-label-{0}'.format(resolvedCommentId)).find('.resolved').show();
175 $('#comment-label-{0}'.format(resolvedCommentId)).find('.resolved').show();
193 $('#comment-label-{0}'.format(resolvedCommentId)).find('.resolve').hide();
176 $('#comment-label-{0}'.format(resolvedCommentId)).find('.resolve').hide();
194 };
177 };
195
178
196 this.isAllowedToSubmit = function() {
179 this.isAllowedToSubmit = function() {
197 return !$(this.submitButton).prop('disabled');
180 return !$(this.submitButton).prop('disabled');
198 };
181 };
199
182
200 this.initStatusChangeSelector = function(){
183 this.initStatusChangeSelector = function(){
201 var formatChangeStatus = function(state, escapeMarkup) {
184 var formatChangeStatus = function(state, escapeMarkup) {
202 var originalOption = state.element;
185 var originalOption = state.element;
203 return '<div class="flag_status ' + $(originalOption).data('status') + ' pull-left"></div>' +
186 return '<div class="flag_status ' + $(originalOption).data('status') + ' pull-left"></div>' +
204 '<span>' + escapeMarkup(state.text) + '</span>';
187 '<span>' + escapeMarkup(state.text) + '</span>';
205 };
188 };
206 var formatResult = function(result, container, query, escapeMarkup) {
189 var formatResult = function(result, container, query, escapeMarkup) {
207 return formatChangeStatus(result, escapeMarkup);
190 return formatChangeStatus(result, escapeMarkup);
208 };
191 };
209
192
210 var formatSelection = function(data, container, escapeMarkup) {
193 var formatSelection = function(data, container, escapeMarkup) {
211 return formatChangeStatus(data, escapeMarkup);
194 return formatChangeStatus(data, escapeMarkup);
212 };
195 };
213
196
214 $(this.submitForm).find(this.statusChange).select2({
197 $(this.submitForm).find(this.statusChange).select2({
215 placeholder: _gettext('Status Review'),
198 placeholder: _gettext('Status Review'),
216 formatResult: formatResult,
199 formatResult: formatResult,
217 formatSelection: formatSelection,
200 formatSelection: formatSelection,
218 containerCssClass: "drop-menu status_box_menu",
201 containerCssClass: "drop-menu status_box_menu",
219 dropdownCssClass: "drop-menu-dropdown",
202 dropdownCssClass: "drop-menu-dropdown",
220 dropdownAutoWidth: true,
203 dropdownAutoWidth: true,
221 minimumResultsForSearch: -1
204 minimumResultsForSearch: -1
222 });
205 });
223 $(this.submitForm).find(this.statusChange).on('change', function() {
206 $(this.submitForm).find(this.statusChange).on('change', function() {
224 var status = self.getCommentStatus();
207 var status = self.getCommentStatus();
225 if (status && !self.isInline()) {
208 if (status && !self.isInline()) {
226 $(self.submitButton).prop('disabled', false);
209 $(self.submitButton).prop('disabled', false);
227 }
210 }
228
211
229 var placeholderText = _gettext('Comment text will be set automatically based on currently selected status ({0}) ...').format(status);
212 var placeholderText = _gettext('Comment text will be set automatically based on currently selected status ({0}) ...').format(status);
230 self.setPlaceholder(placeholderText)
213 self.setPlaceholder(placeholderText)
231 })
214 })
232 };
215 };
233
216
234 // reset the comment form into it's original state
217 // reset the comment form into it's original state
235 this.resetCommentFormState = function(content) {
218 this.resetCommentFormState = function(content) {
236 content = content || '';
219 content = content || '';
237
220
238 $(this.editContainer).show();
221 $(this.editContainer).show();
239 $(this.editButton).parent().addClass('active');
222 $(this.editButton).parent().addClass('active');
240
223
241 $(this.previewContainer).hide();
224 $(this.previewContainer).hide();
242 $(this.previewButton).parent().removeClass('active');
225 $(this.previewButton).parent().removeClass('active');
243
226
244 this.setActionButtonsDisabled(true);
227 this.setActionButtonsDisabled(true);
245 self.cm.setValue(content);
228 self.cm.setValue(content);
246 self.cm.setOption("readOnly", false);
229 self.cm.setOption("readOnly", false);
247
230
248 if (this.resolvesId) {
231 if (this.resolvesId) {
249 // destroy the resolve action
232 // destroy the resolve action
250 $(this.resolvesId).parent().remove();
233 $(this.resolvesId).parent().remove();
251 }
234 }
252
235
253 $(this.statusChange).select2('readonly', false);
236 $(this.statusChange).select2('readonly', false);
254 };
237 };
255
238
256 this.submitAjaxPOST = function(url, postData, successHandler, failHandler) {
239 this.submitAjaxPOST = function(url, postData, successHandler, failHandler) {
257 failHandler = failHandler || function() {};
240 failHandler = failHandler || function() {};
258 var postData = toQueryString(postData);
241 var postData = toQueryString(postData);
259 var request = $.ajax({
242 var request = $.ajax({
260 url: url,
243 url: url,
261 type: 'POST',
244 type: 'POST',
262 data: postData,
245 data: postData,
263 headers: {'X-PARTIAL-XHR': true}
246 headers: {'X-PARTIAL-XHR': true}
264 })
247 })
265 .done(function(data) {
248 .done(function(data) {
266 successHandler(data);
249 successHandler(data);
267 })
250 })
268 .fail(function(data, textStatus, errorThrown){
251 .fail(function(data, textStatus, errorThrown){
269 alert(
252 alert(
270 "Error while submitting comment.\n" +
253 "Error while submitting comment.\n" +
271 "Error code {0} ({1}).".format(data.status, data.statusText));
254 "Error code {0} ({1}).".format(data.status, data.statusText));
272 failHandler()
255 failHandler()
273 });
256 });
274 return request;
257 return request;
275 };
258 };
276
259
277 // overwrite a submitHandler, we need to do it for inline comments
260 // overwrite a submitHandler, we need to do it for inline comments
278 this.setHandleFormSubmit = function(callback) {
261 this.setHandleFormSubmit = function(callback) {
279 this.handleFormSubmit = callback;
262 this.handleFormSubmit = callback;
280 };
263 };
281
264
282 // default handler for for submit for main comments
265 // default handler for for submit for main comments
283 this.handleFormSubmit = function() {
266 this.handleFormSubmit = function() {
284 var text = self.cm.getValue();
267 var text = self.cm.getValue();
285 var status = self.getCommentStatus();
268 var status = self.getCommentStatus();
286 var commentType = self.getCommentType();
269 var commentType = self.getCommentType();
287 var resolvesCommentId = self.getResolvesId();
270 var resolvesCommentId = self.getResolvesId();
288
271
289 if (text === "" && !status) {
272 if (text === "" && !status) {
290 return;
273 return;
291 }
274 }
292
275
293 var excludeCancelBtn = false;
276 var excludeCancelBtn = false;
294 var submitEvent = true;
277 var submitEvent = true;
295 self.setActionButtonsDisabled(true, excludeCancelBtn, submitEvent);
278 self.setActionButtonsDisabled(true, excludeCancelBtn, submitEvent);
296 self.cm.setOption("readOnly", true);
279 self.cm.setOption("readOnly", true);
297
280
298 var postData = {
281 var postData = {
299 'text': text,
282 'text': text,
300 'changeset_status': status,
283 'changeset_status': status,
301 'comment_type': commentType,
284 'comment_type': commentType,
302 'csrf_token': CSRF_TOKEN
285 'csrf_token': CSRF_TOKEN
303 };
286 };
304 if (resolvesCommentId){
287 if (resolvesCommentId){
305 postData['resolves_comment_id'] = resolvesCommentId;
288 postData['resolves_comment_id'] = resolvesCommentId;
306 }
289 }
307 var submitSuccessCallback = function(o) {
290 var submitSuccessCallback = function(o) {
308 if (status) {
291 if (status) {
309 location.reload(true);
292 location.reload(true);
310 } else {
293 } else {
311 $('#injected_page_comments').append(o.rendered_text);
294 $('#injected_page_comments').append(o.rendered_text);
312 self.resetCommentFormState();
295 self.resetCommentFormState();
313 timeagoActivate();
296 timeagoActivate();
314
297
315 // mark visually which comment was resolved
298 // mark visually which comment was resolved
316 if (resolvesCommentId) {
299 if (resolvesCommentId) {
317 self.markCommentResolved(resolvesCommentId);
300 self.markCommentResolved(resolvesCommentId);
318 }
301 }
319 }
302 }
320 };
303 };
321 var submitFailCallback = function(){
304 var submitFailCallback = function(){
322 self.resetCommentFormState(text);
305 self.resetCommentFormState(text);
323 };
306 };
324 self.submitAjaxPOST(
307 self.submitAjaxPOST(
325 self.submitUrl, postData, submitSuccessCallback, submitFailCallback);
308 self.submitUrl, postData, submitSuccessCallback, submitFailCallback);
326 };
309 };
327
310
328 this.previewSuccessCallback = function(o) {
311 this.previewSuccessCallback = function(o) {
329 $(self.previewBoxSelector).html(o);
312 $(self.previewBoxSelector).html(o);
330 $(self.previewBoxSelector).removeClass('unloaded');
313 $(self.previewBoxSelector).removeClass('unloaded');
331
314
332 // swap buttons, making preview active
315 // swap buttons, making preview active
333 $(self.previewButton).parent().addClass('active');
316 $(self.previewButton).parent().addClass('active');
334 $(self.editButton).parent().removeClass('active');
317 $(self.editButton).parent().removeClass('active');
335
318
336 // unlock buttons
319 // unlock buttons
337 self.setActionButtonsDisabled(false);
320 self.setActionButtonsDisabled(false);
338 };
321 };
339
322
340 this.setActionButtonsDisabled = function(state, excludeCancelBtn, submitEvent) {
323 this.setActionButtonsDisabled = function(state, excludeCancelBtn, submitEvent) {
341 excludeCancelBtn = excludeCancelBtn || false;
324 excludeCancelBtn = excludeCancelBtn || false;
342 submitEvent = submitEvent || false;
325 submitEvent = submitEvent || false;
343
326
344 $(this.editButton).prop('disabled', state);
327 $(this.editButton).prop('disabled', state);
345 $(this.previewButton).prop('disabled', state);
328 $(this.previewButton).prop('disabled', state);
346
329
347 if (!excludeCancelBtn) {
330 if (!excludeCancelBtn) {
348 $(this.cancelButton).prop('disabled', state);
331 $(this.cancelButton).prop('disabled', state);
349 }
332 }
350
333
351 var submitState = state;
334 var submitState = state;
352 if (!submitEvent && this.getCommentStatus() && !this.lineNo) {
335 if (!submitEvent && this.getCommentStatus() && !this.lineNo) {
353 // if the value of commit review status is set, we allow
336 // if the value of commit review status is set, we allow
354 // submit button, but only on Main form, lineNo means inline
337 // submit button, but only on Main form, lineNo means inline
355 submitState = false
338 submitState = false
356 }
339 }
357 $(this.submitButton).prop('disabled', submitState);
340 $(this.submitButton).prop('disabled', submitState);
358 if (submitEvent) {
341 if (submitEvent) {
359 $(this.submitButton).val(_gettext('Submitting...'));
342 $(this.submitButton).val(_gettext('Submitting...'));
360 } else {
343 } else {
361 $(this.submitButton).val(this.submitButtonText);
344 $(this.submitButton).val(this.submitButtonText);
362 }
345 }
363
346
364 };
347 };
365
348
366 // lock preview/edit/submit buttons on load, but exclude cancel button
349 // lock preview/edit/submit buttons on load, but exclude cancel button
367 var excludeCancelBtn = true;
350 var excludeCancelBtn = true;
368 this.setActionButtonsDisabled(true, excludeCancelBtn);
351 this.setActionButtonsDisabled(true, excludeCancelBtn);
369
352
370 // anonymous users don't have access to initialized CM instance
353 // anonymous users don't have access to initialized CM instance
371 if (this.cm !== undefined){
354 if (this.cm !== undefined){
372 this.cm.on('change', function(cMirror) {
355 this.cm.on('change', function(cMirror) {
373 if (cMirror.getValue() === "") {
356 if (cMirror.getValue() === "") {
374 self.setActionButtonsDisabled(true, excludeCancelBtn)
357 self.setActionButtonsDisabled(true, excludeCancelBtn)
375 } else {
358 } else {
376 self.setActionButtonsDisabled(false, excludeCancelBtn)
359 self.setActionButtonsDisabled(false, excludeCancelBtn)
377 }
360 }
378 });
361 });
379 }
362 }
380
363
381 $(this.editButton).on('click', function(e) {
364 $(this.editButton).on('click', function(e) {
382 e.preventDefault();
365 e.preventDefault();
383
366
384 $(self.previewButton).parent().removeClass('active');
367 $(self.previewButton).parent().removeClass('active');
385 $(self.previewContainer).hide();
368 $(self.previewContainer).hide();
386
369
387 $(self.editButton).parent().addClass('active');
370 $(self.editButton).parent().addClass('active');
388 $(self.editContainer).show();
371 $(self.editContainer).show();
389
372
390 });
373 });
391
374
392 $(this.previewButton).on('click', function(e) {
375 $(this.previewButton).on('click', function(e) {
393 e.preventDefault();
376 e.preventDefault();
394 var text = self.cm.getValue();
377 var text = self.cm.getValue();
395
378
396 if (text === "") {
379 if (text === "") {
397 return;
380 return;
398 }
381 }
399
382
400 var postData = {
383 var postData = {
401 'text': text,
384 'text': text,
402 'renderer': templateContext.visual.default_renderer,
385 'renderer': templateContext.visual.default_renderer,
403 'csrf_token': CSRF_TOKEN
386 'csrf_token': CSRF_TOKEN
404 };
387 };
405
388
406 // lock ALL buttons on preview
389 // lock ALL buttons on preview
407 self.setActionButtonsDisabled(true);
390 self.setActionButtonsDisabled(true);
408
391
409 $(self.previewBoxSelector).addClass('unloaded');
392 $(self.previewBoxSelector).addClass('unloaded');
410 $(self.previewBoxSelector).html(_gettext('Loading ...'));
393 $(self.previewBoxSelector).html(_gettext('Loading ...'));
411
394
412 $(self.editContainer).hide();
395 $(self.editContainer).hide();
413 $(self.previewContainer).show();
396 $(self.previewContainer).show();
414
397
415 // by default we reset state of comment preserving the text
398 // by default we reset state of comment preserving the text
416 var previewFailCallback = function(){
399 var previewFailCallback = function(){
417 self.resetCommentFormState(text)
400 self.resetCommentFormState(text)
418 };
401 };
419 self.submitAjaxPOST(
402 self.submitAjaxPOST(
420 self.previewUrl, postData, self.previewSuccessCallback,
403 self.previewUrl, postData, self.previewSuccessCallback,
421 previewFailCallback);
404 previewFailCallback);
422
405
423 $(self.previewButton).parent().addClass('active');
406 $(self.previewButton).parent().addClass('active');
424 $(self.editButton).parent().removeClass('active');
407 $(self.editButton).parent().removeClass('active');
425 });
408 });
426
409
427 $(this.submitForm).submit(function(e) {
410 $(this.submitForm).submit(function(e) {
428 e.preventDefault();
411 e.preventDefault();
429 var allowedToSubmit = self.isAllowedToSubmit();
412 var allowedToSubmit = self.isAllowedToSubmit();
430 if (!allowedToSubmit){
413 if (!allowedToSubmit){
431 return false;
414 return false;
432 }
415 }
433 self.handleFormSubmit();
416 self.handleFormSubmit();
434 });
417 });
435
418
436 }
419 }
437
420
438 return CommentForm;
421 return CommentForm;
439 });
422 });
440
423
441 /* comments controller */
424 /* comments controller */
442 var CommentsController = function() {
425 var CommentsController = function() {
443 var mainComment = '#text';
426 var mainComment = '#text';
444 var self = this;
427 var self = this;
445
428
446 this.cancelComment = function(node) {
429 this.cancelComment = function(node) {
447 var $node = $(node);
430 var $node = $(node);
448 var $td = $node.closest('td');
431 var $td = $node.closest('td');
449 $node.closest('.comment-inline-form').remove();
432 $node.closest('.comment-inline-form').remove();
450 return false;
433 return false;
451 };
434 };
452
435
453 this.getLineNumber = function(node) {
436 this.getLineNumber = function(node) {
454 var $node = $(node);
437 var $node = $(node);
455 return $node.closest('td').attr('data-line-number');
438 return $node.closest('td').attr('data-line-number');
456 };
439 };
457
440
458 this.scrollToComment = function(node, offset, outdated) {
441 this.scrollToComment = function(node, offset, outdated) {
459 var outdated = outdated || false;
442 var outdated = outdated || false;
460 var klass = outdated ? 'div.comment-outdated' : 'div.comment-current';
443 var klass = outdated ? 'div.comment-outdated' : 'div.comment-current';
461
444
462 if (!node) {
445 if (!node) {
463 node = $('.comment-selected');
446 node = $('.comment-selected');
464 if (!node.length) {
447 if (!node.length) {
465 node = $('comment-current')
448 node = $('comment-current')
466 }
449 }
467 }
450 }
468 $comment = $(node).closest(klass);
451 $comment = $(node).closest(klass);
469 $comments = $(klass);
452 $comments = $(klass);
470
453
471 $('.comment-selected').removeClass('comment-selected');
454 $('.comment-selected').removeClass('comment-selected');
472
455
473 var nextIdx = $(klass).index($comment) + offset;
456 var nextIdx = $(klass).index($comment) + offset;
474 if (nextIdx >= $comments.length) {
457 if (nextIdx >= $comments.length) {
475 nextIdx = 0;
458 nextIdx = 0;
476 }
459 }
477 var $next = $(klass).eq(nextIdx);
460 var $next = $(klass).eq(nextIdx);
478 var $cb = $next.closest('.cb');
461 var $cb = $next.closest('.cb');
479 $cb.removeClass('cb-collapsed');
462 $cb.removeClass('cb-collapsed');
480
463
481 var $filediffCollapseState = $cb.closest('.filediff').prev();
464 var $filediffCollapseState = $cb.closest('.filediff').prev();
482 $filediffCollapseState.prop('checked', false);
465 $filediffCollapseState.prop('checked', false);
483 $next.addClass('comment-selected');
466 $next.addClass('comment-selected');
484 scrollToElement($next);
467 scrollToElement($next);
485 return false;
468 return false;
486 };
469 };
487
470
488 this.nextComment = function(node) {
471 this.nextComment = function(node) {
489 return self.scrollToComment(node, 1);
472 return self.scrollToComment(node, 1);
490 };
473 };
491
474
492 this.prevComment = function(node) {
475 this.prevComment = function(node) {
493 return self.scrollToComment(node, -1);
476 return self.scrollToComment(node, -1);
494 };
477 };
495
478
496 this.nextOutdatedComment = function(node) {
479 this.nextOutdatedComment = function(node) {
497 return self.scrollToComment(node, 1, true);
480 return self.scrollToComment(node, 1, true);
498 };
481 };
499
482
500 this.prevOutdatedComment = function(node) {
483 this.prevOutdatedComment = function(node) {
501 return self.scrollToComment(node, -1, true);
484 return self.scrollToComment(node, -1, true);
502 };
485 };
503
486
504 this.deleteComment = function(node) {
487 this.deleteComment = function(node) {
505 if (!confirm(_gettext('Delete this comment?'))) {
488 if (!confirm(_gettext('Delete this comment?'))) {
506 return false;
489 return false;
507 }
490 }
508 var $node = $(node);
491 var $node = $(node);
509 var $td = $node.closest('td');
492 var $td = $node.closest('td');
510 var $comment = $node.closest('.comment');
493 var $comment = $node.closest('.comment');
511 var comment_id = $comment.attr('data-comment-id');
494 var comment_id = $comment.attr('data-comment-id');
512 var url = AJAX_COMMENT_DELETE_URL.replace('__COMMENT_ID__', comment_id);
495 var url = AJAX_COMMENT_DELETE_URL.replace('__COMMENT_ID__', comment_id);
513 var postData = {
496 var postData = {
514 '_method': 'delete',
497 '_method': 'delete',
515 'csrf_token': CSRF_TOKEN
498 'csrf_token': CSRF_TOKEN
516 };
499 };
517
500
518 $comment.addClass('comment-deleting');
501 $comment.addClass('comment-deleting');
519 $comment.hide('fast');
502 $comment.hide('fast');
520
503
521 var success = function(response) {
504 var success = function(response) {
522 $comment.remove();
505 $comment.remove();
523 return false;
506 return false;
524 };
507 };
525 var failure = function(data, textStatus, xhr) {
508 var failure = function(data, textStatus, xhr) {
526 alert("error processing request: " + textStatus);
509 alert("error processing request: " + textStatus);
527 $comment.show('fast');
510 $comment.show('fast');
528 $comment.removeClass('comment-deleting');
511 $comment.removeClass('comment-deleting');
529 return false;
512 return false;
530 };
513 };
531 ajaxPOST(url, postData, success, failure);
514 ajaxPOST(url, postData, success, failure);
532 };
515 };
533
516
534 this.toggleWideMode = function (node) {
517 this.toggleWideMode = function (node) {
535 if ($('#content').hasClass('wrapper')) {
518 if ($('#content').hasClass('wrapper')) {
536 $('#content').removeClass("wrapper");
519 $('#content').removeClass("wrapper");
537 $('#content').addClass("wide-mode-wrapper");
520 $('#content').addClass("wide-mode-wrapper");
538 $(node).addClass('btn-success');
521 $(node).addClass('btn-success');
539 } else {
522 } else {
540 $('#content').removeClass("wide-mode-wrapper");
523 $('#content').removeClass("wide-mode-wrapper");
541 $('#content').addClass("wrapper");
524 $('#content').addClass("wrapper");
542 $(node).removeClass('btn-success');
525 $(node).removeClass('btn-success');
543 }
526 }
544 return false;
527 return false;
545 };
528 };
546
529
547 this.toggleComments = function(node, show) {
530 this.toggleComments = function(node, show) {
548 var $filediff = $(node).closest('.filediff');
531 var $filediff = $(node).closest('.filediff');
549 if (show === true) {
532 if (show === true) {
550 $filediff.removeClass('hide-comments');
533 $filediff.removeClass('hide-comments');
551 } else if (show === false) {
534 } else if (show === false) {
552 $filediff.find('.hide-line-comments').removeClass('hide-line-comments');
535 $filediff.find('.hide-line-comments').removeClass('hide-line-comments');
553 $filediff.addClass('hide-comments');
536 $filediff.addClass('hide-comments');
554 } else {
537 } else {
555 $filediff.find('.hide-line-comments').removeClass('hide-line-comments');
538 $filediff.find('.hide-line-comments').removeClass('hide-line-comments');
556 $filediff.toggleClass('hide-comments');
539 $filediff.toggleClass('hide-comments');
557 }
540 }
558 return false;
541 return false;
559 };
542 };
560
543
561 this.toggleLineComments = function(node) {
544 this.toggleLineComments = function(node) {
562 self.toggleComments(node, true);
545 self.toggleComments(node, true);
563 var $node = $(node);
546 var $node = $(node);
564 $node.closest('tr').toggleClass('hide-line-comments');
547 $node.closest('tr').toggleClass('hide-line-comments');
565 };
548 };
566
549
567 this.createCommentForm = function(formElement, lineno, placeholderText, initAutocompleteActions, resolvesCommentId){
550 this.createCommentForm = function(formElement, lineno, placeholderText, initAutocompleteActions, resolvesCommentId){
568 var pullRequestId = templateContext.pull_request_data.pull_request_id;
551 var pullRequestId = templateContext.pull_request_data.pull_request_id;
569 var commitId = templateContext.commit_data.commit_id;
552 var commitId = templateContext.commit_data.commit_id;
570
553
571 var commentForm = new CommentForm(
554 var commentForm = new CommentForm(
572 formElement, commitId, pullRequestId, lineno, initAutocompleteActions, resolvesCommentId);
555 formElement, commitId, pullRequestId, lineno, initAutocompleteActions, resolvesCommentId);
573 var cm = commentForm.getCmInstance();
556 var cm = commentForm.getCmInstance();
574
557
575 if (resolvesCommentId){
558 if (resolvesCommentId){
576 var placeholderText = _gettext('Leave a comment, or click resolve button to resolve TODO comment #{0}').format(resolvesCommentId);
559 var placeholderText = _gettext('Leave a comment, or click resolve button to resolve TODO comment #{0}').format(resolvesCommentId);
577 }
560 }
578
561
579 setTimeout(function() {
562 setTimeout(function() {
580 // callbacks
563 // callbacks
581 if (cm !== undefined) {
564 if (cm !== undefined) {
582 commentForm.setPlaceholder(placeholderText);
565 commentForm.setPlaceholder(placeholderText);
583 if (commentForm.isInline()) {
566 if (commentForm.isInline()) {
584 cm.focus();
567 cm.focus();
585 cm.refresh();
568 cm.refresh();
586 }
569 }
587 }
570 }
588 }, 10);
571 }, 10);
589
572
590 // trigger scrolldown to the resolve comment, since it might be away
573 // trigger scrolldown to the resolve comment, since it might be away
591 // from the clicked
574 // from the clicked
592 if (resolvesCommentId){
575 if (resolvesCommentId){
593 var actionNode = $(commentForm.resolvesActionId).offset();
576 var actionNode = $(commentForm.resolvesActionId).offset();
594
577
595 setTimeout(function() {
578 setTimeout(function() {
596 if (actionNode) {
579 if (actionNode) {
597 $('body, html').animate({scrollTop: actionNode.top}, 10);
580 $('body, html').animate({scrollTop: actionNode.top}, 10);
598 }
581 }
599 }, 100);
582 }, 100);
600 }
583 }
601
584
602 return commentForm;
585 return commentForm;
603 };
586 };
604
587
605 this.createGeneralComment = function(lineNo, placeholderText, resolvesCommentId){
588 this.createGeneralComment = function(lineNo, placeholderText, resolvesCommentId){
606
589
607 var tmpl = $('#cb-comment-general-form-template').html();
590 var tmpl = $('#cb-comment-general-form-template').html();
608 tmpl = tmpl.format(null, 'general');
591 tmpl = tmpl.format(null, 'general');
609 var $form = $(tmpl);
592 var $form = $(tmpl);
610
593
611 var curForm = $('#cb-comment-general-form-placeholder').find('form');
594 var curForm = $('#cb-comment-general-form-placeholder').find('form');
612 if (curForm){
595 if (curForm){
613 curForm.remove();
596 curForm.remove();
614 }
597 }
615 $('#cb-comment-general-form-placeholder').append($form);
598 $('#cb-comment-general-form-placeholder').append($form);
616
599
617 var _form = $($form[0]);
600 var _form = $($form[0]);
618 var commentForm = this.createCommentForm(
601 var commentForm = this.createCommentForm(
619 _form, lineNo, placeholderText, true, resolvesCommentId);
602 _form, lineNo, placeholderText, true, resolvesCommentId);
620 commentForm.initStatusChangeSelector();
603 commentForm.initStatusChangeSelector();
621 };
604 };
622
605
623 this.createComment = function(node, resolutionComment) {
606 this.createComment = function(node, resolutionComment) {
624 var resolvesCommentId = resolutionComment || null;
607 var resolvesCommentId = resolutionComment || null;
625 var $node = $(node);
608 var $node = $(node);
626 var $td = $node.closest('td');
609 var $td = $node.closest('td');
627 var $form = $td.find('.comment-inline-form');
610 var $form = $td.find('.comment-inline-form');
628
611
629 if (!$form.length) {
612 if (!$form.length) {
630
613
631 var $filediff = $node.closest('.filediff');
614 var $filediff = $node.closest('.filediff');
632 $filediff.removeClass('hide-comments');
615 $filediff.removeClass('hide-comments');
633 var f_path = $filediff.attr('data-f-path');
616 var f_path = $filediff.attr('data-f-path');
634 var lineno = self.getLineNumber(node);
617 var lineno = self.getLineNumber(node);
635 // create a new HTML from template
618 // create a new HTML from template
636 var tmpl = $('#cb-comment-inline-form-template').html();
619 var tmpl = $('#cb-comment-inline-form-template').html();
637 tmpl = tmpl.format(f_path, lineno);
620 tmpl = tmpl.format(f_path, lineno);
638 $form = $(tmpl);
621 $form = $(tmpl);
639
622
640 var $comments = $td.find('.inline-comments');
623 var $comments = $td.find('.inline-comments');
641 if (!$comments.length) {
624 if (!$comments.length) {
642 $comments = $(
625 $comments = $(
643 $('#cb-comments-inline-container-template').html());
626 $('#cb-comments-inline-container-template').html());
644 $td.append($comments);
627 $td.append($comments);
645 }
628 }
646
629
647 $td.find('.cb-comment-add-button').before($form);
630 $td.find('.cb-comment-add-button').before($form);
648
631
649 var placeholderText = _gettext('Leave a comment on line {0}.').format(lineno);
632 var placeholderText = _gettext('Leave a comment on line {0}.').format(lineno);
650 var _form = $($form[0]).find('form');
633 var _form = $($form[0]).find('form');
651
634
652 var commentForm = this.createCommentForm(
635 var commentForm = this.createCommentForm(
653 _form, lineno, placeholderText, false, resolvesCommentId);
636 _form, lineno, placeholderText, false, resolvesCommentId);
654
637
655 $.Topic('/ui/plugins/code/comment_form_built').prepareOrPublish({
638 $.Topic('/ui/plugins/code/comment_form_built').prepareOrPublish({
656 form: _form,
639 form: _form,
657 parent: $td[0],
640 parent: $td[0],
658 lineno: lineno,
641 lineno: lineno,
659 f_path: f_path}
642 f_path: f_path}
660 );
643 );
661
644
662 // set a CUSTOM submit handler for inline comments.
645 // set a CUSTOM submit handler for inline comments.
663 commentForm.setHandleFormSubmit(function(o) {
646 commentForm.setHandleFormSubmit(function(o) {
664 var text = commentForm.cm.getValue();
647 var text = commentForm.cm.getValue();
665 var commentType = commentForm.getCommentType();
648 var commentType = commentForm.getCommentType();
666 var resolvesCommentId = commentForm.getResolvesId();
649 var resolvesCommentId = commentForm.getResolvesId();
667
650
668 if (text === "") {
651 if (text === "") {
669 return;
652 return;
670 }
653 }
671
654
672 if (lineno === undefined) {
655 if (lineno === undefined) {
673 alert('missing line !');
656 alert('missing line !');
674 return;
657 return;
675 }
658 }
676 if (f_path === undefined) {
659 if (f_path === undefined) {
677 alert('missing file path !');
660 alert('missing file path !');
678 return;
661 return;
679 }
662 }
680
663
681 var excludeCancelBtn = false;
664 var excludeCancelBtn = false;
682 var submitEvent = true;
665 var submitEvent = true;
683 commentForm.setActionButtonsDisabled(true, excludeCancelBtn, submitEvent);
666 commentForm.setActionButtonsDisabled(true, excludeCancelBtn, submitEvent);
684 commentForm.cm.setOption("readOnly", true);
667 commentForm.cm.setOption("readOnly", true);
685 var postData = {
668 var postData = {
686 'text': text,
669 'text': text,
687 'f_path': f_path,
670 'f_path': f_path,
688 'line': lineno,
671 'line': lineno,
689 'comment_type': commentType,
672 'comment_type': commentType,
690 'csrf_token': CSRF_TOKEN
673 'csrf_token': CSRF_TOKEN
691 };
674 };
692 if (resolvesCommentId){
675 if (resolvesCommentId){
693 postData['resolves_comment_id'] = resolvesCommentId;
676 postData['resolves_comment_id'] = resolvesCommentId;
694 }
677 }
695
678
696 var submitSuccessCallback = function(json_data) {
679 var submitSuccessCallback = function(json_data) {
697 $form.remove();
680 $form.remove();
698 try {
681 try {
699 var html = json_data.rendered_text;
682 var html = json_data.rendered_text;
700 var lineno = json_data.line_no;
683 var lineno = json_data.line_no;
701 var target_id = json_data.target_id;
684 var target_id = json_data.target_id;
702
685
703 $comments.find('.cb-comment-add-button').before(html);
686 $comments.find('.cb-comment-add-button').before(html);
704
687
705 //mark visually which comment was resolved
688 //mark visually which comment was resolved
706 if (resolvesCommentId) {
689 if (resolvesCommentId) {
707 commentForm.markCommentResolved(resolvesCommentId);
690 commentForm.markCommentResolved(resolvesCommentId);
708 }
691 }
709
692
710 } catch (e) {
693 } catch (e) {
711 console.error(e);
694 console.error(e);
712 }
695 }
713
696
714 // re trigger the linkification of next/prev navigation
697 // re trigger the linkification of next/prev navigation
715 linkifyComments($('.inline-comment-injected'));
698 linkifyComments($('.inline-comment-injected'));
716 timeagoActivate();
699 timeagoActivate();
717 commentForm.setActionButtonsDisabled(false);
700 commentForm.setActionButtonsDisabled(false);
718
701
719 };
702 };
720 var submitFailCallback = function(){
703 var submitFailCallback = function(){
721 commentForm.resetCommentFormState(text)
704 commentForm.resetCommentFormState(text)
722 };
705 };
723 commentForm.submitAjaxPOST(
706 commentForm.submitAjaxPOST(
724 commentForm.submitUrl, postData, submitSuccessCallback, submitFailCallback);
707 commentForm.submitUrl, postData, submitSuccessCallback, submitFailCallback);
725 });
708 });
726 }
709 }
727
710
728 $form.addClass('comment-inline-form-open');
711 $form.addClass('comment-inline-form-open');
729 };
712 };
730
713
731 this.createResolutionComment = function(commentId){
714 this.createResolutionComment = function(commentId){
732 // hide the trigger text
715 // hide the trigger text
733 $('#resolve-comment-{0}'.format(commentId)).hide();
716 $('#resolve-comment-{0}'.format(commentId)).hide();
734
717
735 var comment = $('#comment-'+commentId);
718 var comment = $('#comment-'+commentId);
736 var commentData = comment.data();
719 var commentData = comment.data();
737 if (commentData.commentInline) {
720 if (commentData.commentInline) {
738 this.createComment(comment, commentId)
721 this.createComment(comment, commentId)
739 } else {
722 } else {
740 Rhodecode.comments.createGeneralComment('general', "$placeholder", commentId)
723 Rhodecode.comments.createGeneralComment('general', "$placeholder", commentId)
741 }
724 }
742
725
743 return false;
726 return false;
744 };
727 };
745
728
746 this.submitResolution = function(commentId){
729 this.submitResolution = function(commentId){
747 var form = $('#resolve_comment_{0}'.format(commentId)).closest('form');
730 var form = $('#resolve_comment_{0}'.format(commentId)).closest('form');
748 var commentForm = form.get(0).CommentForm;
731 var commentForm = form.get(0).CommentForm;
749
732
750 var cm = commentForm.getCmInstance();
733 var cm = commentForm.getCmInstance();
751 var renderer = templateContext.visual.default_renderer;
734 var renderer = templateContext.visual.default_renderer;
752 if (renderer == 'rst'){
735 if (renderer == 'rst'){
753 var commentUrl = '`#{0} <{1}#comment-{0}>`_'.format(commentId, commentForm.selfUrl);
736 var commentUrl = '`#{0} <{1}#comment-{0}>`_'.format(commentId, commentForm.selfUrl);
754 } else if (renderer == 'markdown') {
737 } else if (renderer == 'markdown') {
755 var commentUrl = '[#{0}]({1}#comment-{0})'.format(commentId, commentForm.selfUrl);
738 var commentUrl = '[#{0}]({1}#comment-{0})'.format(commentId, commentForm.selfUrl);
756 } else {
739 } else {
757 var commentUrl = '{1}#comment-{0}'.format(commentId, commentForm.selfUrl);
740 var commentUrl = '{1}#comment-{0}'.format(commentId, commentForm.selfUrl);
758 }
741 }
759
742
760 cm.setValue(_gettext('TODO from comment {0} was fixed.').format(commentUrl));
743 cm.setValue(_gettext('TODO from comment {0} was fixed.').format(commentUrl));
761 form.submit();
744 form.submit();
762 return false;
745 return false;
763 };
746 };
764
747
765 this.renderInlineComments = function(file_comments) {
748 this.renderInlineComments = function(file_comments) {
766 show_add_button = typeof show_add_button !== 'undefined' ? show_add_button : true;
749 show_add_button = typeof show_add_button !== 'undefined' ? show_add_button : true;
767
750
768 for (var i = 0; i < file_comments.length; i++) {
751 for (var i = 0; i < file_comments.length; i++) {
769 var box = file_comments[i];
752 var box = file_comments[i];
770
753
771 var target_id = $(box).attr('target_id');
754 var target_id = $(box).attr('target_id');
772
755
773 // actually comments with line numbers
756 // actually comments with line numbers
774 var comments = box.children;
757 var comments = box.children;
775
758
776 for (var j = 0; j < comments.length; j++) {
759 for (var j = 0; j < comments.length; j++) {
777 var data = {
760 var data = {
778 'rendered_text': comments[j].outerHTML,
761 'rendered_text': comments[j].outerHTML,
779 'line_no': $(comments[j]).attr('line'),
762 'line_no': $(comments[j]).attr('line'),
780 'target_id': target_id
763 'target_id': target_id
781 };
764 };
782 }
765 }
783 }
766 }
784
767
785 // since order of injection is random, we're now re-iterating
768 // since order of injection is random, we're now re-iterating
786 // from correct order and filling in links
769 // from correct order and filling in links
787 linkifyComments($('.inline-comment-injected'));
770 linkifyComments($('.inline-comment-injected'));
788 firefoxAnchorFix();
771 firefoxAnchorFix();
789 };
772 };
790
773
791 };
774 };
General Comments 0
You need to be logged in to leave comments. Login now