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