Commit 140652e9b019addaf7022e18b6816ecb36eee80c

Authored by Riyad Preukschas
1 parent 5d3fb35c

Fix common form and note preview

app/assets/javascripts/notes.js
@@ -10,24 +10,25 @@ var NoteList = { @@ -10,24 +10,25 @@ var NoteList = {
10 reversed: false, 10 reversed: false,
11 11
12 init: function(tid, tt, path) { 12 init: function(tid, tt, path) {
13 - this.notes_path = path + ".js";  
14 - this.target_id = tid;  
15 - this.target_type = tt;  
16 - this.reversed = $("#notes-list").is(".reversed");  
17 - this.target_params = "target_type=" + this.target_type + "&target_id=" + this.target_id;  
18 -  
19 - if(this.reversed) {  
20 - var textarea = $(".note-text");  
21 - $('.note_advanced_opts').hide(); 13 + NoteList.notes_path = path + ".js";
  14 + NoteList.target_id = tid;
  15 + NoteList.target_type = tt;
  16 + NoteList.reversed = $("#notes-list").is(".reversed");
  17 + NoteList.target_params = "target_type=" + NoteList.target_type + "&target_id=" + NoteList.target_id;
  18 +
  19 + if(NoteList.reversed) {
  20 + var form = $("#new_note");
  21 + form.find(".buttons, .note_advanced_opts").hide();
  22 + var textarea = form.find(".js-note-text");
22 textarea.css("height", "40px"); 23 textarea.css("height", "40px");
23 textarea.on("focus", function(){ 24 textarea.on("focus", function(){
24 - $(this).css("height", "80px");  
25 - $('.note_advanced_opts').show(); 25 + textarea.css("height", "80px");
  26 + form.find(".buttons, .note_advanced_opts").show();
26 }); 27 });
27 } 28 }
28 29
29 // get initial set of notes 30 // get initial set of notes
30 - this.getContent(); 31 + NoteList.getContent();
31 32
32 disableButtonIfEmptyField(".js-note-text", ".js-comment-button"); 33 disableButtonIfEmptyField(".js-note-text", ".js-comment-button");
33 34
@@ -37,34 +38,21 @@ var NoteList = { @@ -37,34 +38,21 @@ var NoteList = {
37 $(".file_name").text(filename); 38 $(".file_name").text(filename);
38 }); 39 });
39 40
40 - // Setup note preview  
41 - $(document).on('click', '#preview-link', function(e) {  
42 - $('#preview-note').text('Loading...');  
43 -  
44 - $(this).text($(this).text() === "Edit" ? "Preview" : "Edit");  
45 -  
46 - var note_text = $('#note_note').val();  
47 -  
48 - if(note_text.trim().length === 0) {  
49 - $('#preview-note').text('Nothing to preview.');  
50 - } else {  
51 - $.post($(this).attr('href'), {note: note_text}).success(function(data) {  
52 - $('#preview-note').html(data);  
53 - });  
54 - }  
55 -  
56 - $('#preview-note, #note_note').toggle();  
57 - });+  
58 - 41 + // add a new diff note
59 $(document).on("click", 42 $(document).on("click",
60 ".js-add-diff-note-button", 43 ".js-add-diff-note-button",
61 NoteList.addDiffNote); 44 NoteList.addDiffNote);
62 45
63 - // reply to diff notes 46 + // reply to diff/discussion notes
64 $(document).on("click", 47 $(document).on("click",
65 ".js-discussion-reply-button", 48 ".js-discussion-reply-button",
66 NoteList.replyToDiscussionNote); 49 NoteList.replyToDiscussionNote);
67 50
  51 + // setup note preview
  52 + $(document).on("click",
  53 + ".js-note-preview-button",
  54 + NoteList.previewNote);
  55 +
68 // hide diff note form 56 // hide diff note form
69 $(document).on("click", 57 $(document).on("click",
70 ".js-close-discussion-note-form", 58 ".js-close-discussion-note-form",
@@ -83,8 +71,12 @@ var NoteList = { @@ -83,8 +71,12 @@ var NoteList = {
83 71
84 // clean up previews for forms 72 // clean up previews for forms
85 $(document).on("ajax:complete", ".note-form-holder", function(){ 73 $(document).on("ajax:complete", ".note-form-holder", function(){
86 - $(this).find('#preview-note').hide();  
87 - $(this).find('#note_note').show(); 74 + //$(this).find('.js-note-preview-button').text('Preview');
  75 + //$(this).find('.js-note-preview').hide();
  76 +
  77 + $(this).find('.error').remove();
  78 + $(this).find('.js-note-text').val("");
  79 + $(this).show();
88 }); 80 });
89 }, 81 },
90 82
@@ -124,6 +116,31 @@ var NoteList = { @@ -124,6 +116,31 @@ var NoteList = {
124 }, 116 },
125 117
126 /** 118 /**
  119 + * Shows the note preview.
  120 + *
  121 + * Lets the server render GFM into Html and displays it.
  122 + *
  123 + * Note: uses the Toggler behavior to toggle preview/edit views/buttons
  124 + */
  125 + previewNote: function(e) {
  126 + var form = $(this).closest("form");
  127 + var preview = form.find('.js-note-preview');
  128 + var note_text = form.find('.js-note-text').val();
  129 +
  130 + if(note_text.trim().length === 0) {
  131 + preview.text('Nothing to preview.');
  132 + } else if($(this).data('url')) {
  133 + preview.text('Loading...');
  134 + $.post($(this).data('url'), {note: note_text})
  135 + .success(function(previewData) {
  136 + preview.html(previewData);
  137 + });
  138 + }
  139 +
  140 + e.preventDefault();
  141 + },
  142 +
  143 + /**
127 * Called in response to deleting a note on a diff line. 144 * Called in response to deleting a note on a diff line.
128 * 145 *
129 * Removes the actual note from view. 146 * Removes the actual note from view.
@@ -233,8 +250,8 @@ var NoteList = { @@ -233,8 +250,8 @@ var NoteList = {
233 */ 250 */
234 getContent: function() { 251 getContent: function() {
235 $.ajax({ 252 $.ajax({
236 - url: this.notes_path,  
237 - data: this.target_params, 253 + url: NoteList.notes_path,
  254 + data: NoteList.target_params,
238 complete: function(){ $('.notes-status').removeClass("loading")}, 255 complete: function(){ $('.notes-status').removeClass("loading")},
239 beforeSend: function() { $('.notes-status').addClass("loading") }, 256 beforeSend: function() { $('.notes-status').addClass("loading") },
240 dataType: "script" 257 dataType: "script"
@@ -246,23 +263,23 @@ var NoteList = { @@ -246,23 +263,23 @@ var NoteList = {
246 * Replaces the content of #notes-list with the given html. 263 * Replaces the content of #notes-list with the given html.
247 */ 264 */
248 setContent: function(newNoteIds, html) { 265 setContent: function(newNoteIds, html) {
249 - this.top_id = newNoteIds.first();  
250 - this.bottom_id = newNoteIds.last(); 266 + NoteList.top_id = newNoteIds.first();
  267 + NoteList.bottom_id = newNoteIds.last();
251 $("#notes-list").html(html); 268 $("#notes-list").html(html);
252 269
253 - if (this.reversed) { 270 + if (NoteList.reversed) {
254 // init infinite scrolling 271 // init infinite scrolling
255 - this.initLoadMore(); 272 + NoteList.initLoadMore();
256 273
257 // init getting new notes 274 // init getting new notes
258 - this.initRefreshNew(); 275 + NoteList.initRefreshNew();
259 } 276 }
260 }, 277 },
261 278
262 279
263 /** 280 /**
264 * Handle loading more notes when scrolling to the bottom of the page. 281 * Handle loading more notes when scrolling to the bottom of the page.
265 - * The id of the last note in the list is in this.bottom_id. 282 + * The id of the last note in the list is in NoteList.bottom_id.
266 * 283 *
267 * Set up refreshing only new notes after all notes have been loaded. 284 * Set up refreshing only new notes after all notes have been loaded.
268 */ 285 */
@@ -292,8 +309,8 @@ var NoteList = { @@ -292,8 +309,8 @@ var NoteList = {
292 // only load more notes if there are no "new" notes 309 // only load more notes if there are no "new" notes
293 $('.loading').show(); 310 $('.loading').show();
294 $.ajax({ 311 $.ajax({
295 - url: this.notes_path,  
296 - data: this.target_params + "&loading_more=1&" + (this.reversed ? "before_id" : "after_id") + "=" + this.bottom_id, 312 + url: NoteList.notes_path,
  313 + data: NoteList.target_params + "&loading_more=1&" + (NoteList.reversed ? "before_id" : "after_id") + "=" + NoteList.bottom_id,
297 complete: function(){ $('.notes-status').removeClass("loading")}, 314 complete: function(){ $('.notes-status').removeClass("loading")},
298 beforeSend: function() { $('.notes-status').addClass("loading") }, 315 beforeSend: function() { $('.notes-status').addClass("loading") },
299 dataType: "script" 316 dataType: "script"
@@ -306,8 +323,8 @@ var NoteList = { @@ -306,8 +323,8 @@ var NoteList = {
306 */ 323 */
307 appendMoreNotes: function(newNoteIds, html) { 324 appendMoreNotes: function(newNoteIds, html) {
308 var lastNewNoteId = newNoteIds.last(); 325 var lastNewNoteId = newNoteIds.last();
309 - if(lastNewNoteId != this.bottom_id) {  
310 - this.bottom_id = lastNewNoteId; 326 + if(lastNewNoteId != NoteList.bottom_id) {
  327 + NoteList.bottom_id = lastNewNoteId;
311 $("#notes-list").append(html); 328 $("#notes-list").append(html);
312 } 329 }
313 }, 330 },
@@ -315,17 +332,12 @@ var NoteList = { @@ -315,17 +332,12 @@ var NoteList = {
315 /** 332 /**
316 * Called in response to getMore(). 333 * Called in response to getMore().
317 * Disables loading more notes when scrolling to the bottom of the page. 334 * Disables loading more notes when scrolling to the bottom of the page.
318 - * Initalizes refreshing new notes.  
319 */ 335 */
320 finishedLoadingMore: function() { 336 finishedLoadingMore: function() {
321 - this.loading_more_disabled = true; 337 + NoteList.loading_more_disabled = true;
322 338
323 - // from now on only get new notes  
324 - if (!this.reversed) {  
325 - this.initRefreshNew();  
326 - }  
327 // make sure we are up to date 339 // make sure we are up to date
328 - this.updateVotes(); 340 + NoteList.updateVotes();
329 }, 341 },
330 342
331 343
@@ -334,7 +346,7 @@ var NoteList = { @@ -334,7 +346,7 @@ var NoteList = {
334 * 346 *
335 * New notes are all notes that are created after the site has been loaded. 347 * New notes are all notes that are created after the site has been loaded.
336 * The "old" notes are in #notes-list the "new" ones will be in #new-notes-list. 348 * The "old" notes are in #notes-list the "new" ones will be in #new-notes-list.
337 - * The id of the last "old" note is in this.bottom_id. 349 + * The id of the last "old" note is in NoteList.bottom_id.
338 */ 350 */
339 351
340 352
@@ -350,8 +362,8 @@ var NoteList = { @@ -350,8 +362,8 @@ var NoteList = {
350 */ 362 */
351 getNew: function() { 363 getNew: function() {
352 $.ajax({ 364 $.ajax({
353 - url: this.notes_path,  
354 - data: this.target_params + "&loading_new=1&after_id=" + (this.reversed ? this.top_id : this.bottom_id), 365 + url: NoteList.notes_path,
  366 + data: NoteList.target_params + "&loading_new=1&after_id=" + (NoteList.reversed ? NoteList.top_id : NoteList.bottom_id),
355 dataType: "script" 367 dataType: "script"
356 }); 368 });
357 }, 369 },
@@ -362,21 +374,20 @@ var NoteList = { @@ -362,21 +374,20 @@ var NoteList = {
362 */ 374 */
363 replaceNewNotes: function(newNoteIds, html) { 375 replaceNewNotes: function(newNoteIds, html) {
364 $("#new-notes-list").html(html); 376 $("#new-notes-list").html(html);
365 - this.updateVotes(); 377 + NoteList.updateVotes();
366 }, 378 },
367 379
368 /** 380 /**
369 - * Adds a single note to #new-notes-list. 381 + * Adds a single common note to #(new-)notes-list.
370 */ 382 */
371 appendNewNote: function(id, html) { 383 appendNewNote: function(id, html) {
372 - if (this.reversed) {  
373 - $("#notes-list").prepend(html);  
374 - } else {  
375 - $("#notes-list").append(html);  
376 - }  
377 - this.updateVotes(); 384 + $("#notes-list").append(html);
  385 + NoteList.updateVotes();
378 }, 386 },
379 387
  388 + /**
  389 + * Adds a single discussion note to #(new-)notes-list.
  390 + */
380 appendNewDiscussionNote: function(discussionId, diffRowHtml, noteHtml) { 391 appendNewDiscussionNote: function(discussionId, diffRowHtml, noteHtml) {
381 // is this the first note of discussion? 392 // is this the first note of discussion?
382 var row = $("form[rel='"+discussionId+"']").closest("tr"); 393 var row = $("form[rel='"+discussionId+"']").closest("tr");
@@ -401,7 +412,7 @@ var NoteList = { @@ -401,7 +412,7 @@ var NoteList = {
401 */ 412 */
402 updateVotes: function() { 413 updateVotes: function() {
403 var votes = $("#votes .votes"); 414 var votes = $("#votes .votes");
404 - var notes = $("#notes-list").find(".note .vote"); 415 + var notes = $("#notes-list .note .vote");
405 416
406 // only update if there is a vote display 417 // only update if there is a vote display
407 if (votes.size()) { 418 if (votes.size()) {
app/assets/stylesheets/behaviors.scss
@@ -8,7 +8,7 @@ @@ -8,7 +8,7 @@
8 8
9 // Toggler 9 // Toggler
10 //-------- 10 //--------
11 -.js-toggler-container .turn-on { display: inline-block; } 11 +.js-toggler-container .turn-on { display: inherit; }
12 .js-toggler-container .turn-off { display: none; } 12 .js-toggler-container .turn-off { display: none; }
13 .js-toggler-container.on .turn-on { display: none; } 13 .js-toggler-container.on .turn-on { display: none; }
14 -.js-toggler-container.on .turn-off { display: inline-block; } 14 +.js-toggler-container.on .turn-off { display: inherit; }
app/assets/stylesheets/sections/notes.scss
@@ -310,24 +310,26 @@ p.notify_controls span{ @@ -310,24 +310,26 @@ p.notify_controls span{
310 padding-right: 15px; 310 padding-right: 15px;
311 } 311 }
312 } 312 }
313 - .note-text { 313 + .note_preview {
  314 + margin: 2px;
  315 + border: 1px solid #ddd;
  316 + padding: 10px;
  317 + min-height: 60px;
  318 + background:#f5f5f5;
  319 + }
  320 + .note_text {
314 border: 1px solid #aaa; 321 border: 1px solid #aaa;
315 - box-shadow:none; 322 + box-shadow: none;
316 } 323 }
317 // TODO: end cleanup 324 // TODO: end cleanup
318 } 325 }
319 326
320 // hide the new discussion note form template 327 // hide the new discussion note form template
321 -.note-forms { 328 +#note-forms {
  329 + .note-form-holder {
  330 + margin-top: 5px;
  331 + }
322 .new_discussion_note { 332 .new_discussion_note {
323 display: none; 333 display: none;
324 } 334 }
325 } 335 }
326 -  
327 -.preview_note {  
328 - margin: 2px;  
329 - border: 1px solid #ddd;  
330 - padding: 10px;  
331 - min-height: 60px;  
332 - background:#f5f5f5;  
333 -}  
app/views/notes/_common_form.html.haml
@@ -11,17 +11,32 @@ @@ -11,17 +11,32 @@
11 - @note.errors.full_messages.each do |msg| 11 - @note.errors.full_messages.each do |msg|
12 %div= msg 12 %div= msg
13 13
14 - = f.text_area :note, size: 255, class: 'js-note-text js-gfm-input'  
15 - #preview-note.preview_note.hide  
16 - .hint  
17 - .right Comments are parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}. 14 + .js-toggler-container
  15 + = f.text_area :note, size: 255, class: 'note_text turn-on js-note-text js-gfm-input'
  16 + .note_preview.js-note-preview.hide.turn-off
  17 +
  18 + .hint
  19 + .right Comments are parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}.
18 .clearfix 20 .clearfix
19 21
20 - .row.note_advanced_opts  
21 - .span3 22 + .buttons
22 = f.submit 'Add Comment', class: "btn comment-btn grouped js-comment-button" 23 = f.submit 'Add Comment', class: "btn comment-btn grouped js-comment-button"
23 - = link_to 'Preview', preview_project_notes_path(@project), class: 'btn grouped', id: 'preview-link'  
24 - .span4.notify_opts 24 + %button.btn.grouped.js-note-preview-button.js-toggler-target.turn-on{ data: {url: preview_project_notes_path(@project)} }
  25 + Preview
  26 + %button.btn.grouped.js-note-preview-button.js-toggler-target.turn-off
  27 + Edit
  28 +
  29 + .note_advanced_opts
  30 + .attachments.right
  31 + %h6.left Attachment:
  32 + %span.file_name File name...
  33 +
  34 + .input.input_file
  35 + %a.file_upload.btn.small Upload File
  36 + = f.file_field :attachment, class: "input-file"
  37 + %span.hint Any file less than 10 MB
  38 +
  39 + .notify_opts.right
25 %h6.left Notify via email: 40 %h6.left Notify via email:
26 = label_tag :notify do 41 = label_tag :notify do
27 = check_box_tag :notify, 1, @note.noteable_type != "Commit" 42 = check_box_tag :notify, 1, @note.noteable_type != "Commit"
@@ -31,11 +46,4 @@ @@ -31,11 +46,4 @@
31 = label_tag :notify_author do 46 = label_tag :notify_author do
32 = check_box_tag :notify_author, 1 , @note.noteable_type == "Commit" 47 = check_box_tag :notify_author, 1 , @note.noteable_type == "Commit"
33 %span Commit author 48 %span Commit author
34 - .span5.attachments  
35 - %h6.left Attachment:  
36 - %span.file_name File name...  
37 -  
38 - .input.input_file  
39 - %a.file_upload.btn.small Upload File  
40 - = f.file_field :attachment, class: "input-file"  
41 - %span.hint Any file less than 10 MB 49 + .clearfix
app/views/notes/_create_common_note.js.haml
1 - if note.valid? 1 - if note.valid?
2 - :plain  
3 - $(".note-form-holder .error").remove();  
4 - $('.note-form-holder textarea').val("");  
5 - $('.note-form-holder #preview-link').text('Preview');  
6 - $('.note-form-holder #preview-note').hide();  
7 - $('.note-form-holder').show();  
8 NoteList.appendNewNote(#{note.id}, "#{escape_javascript(render "notes/note", note: note)}"); 2 NoteList.appendNewNote(#{note.id}, "#{escape_javascript(render "notes/note", note: note)}");
9 3
10 - else 4 - else
11 - :plain  
12 - $(".note-form-holder").replaceWith("#{escape_javascript(render 'notes/common_form')}");  
13 - GitLab.GfmAutoComplete.setup(); 5 + $(".note-form-holder").replaceWith("#{escape_javascript(render 'notes/common_form')}");
  6 + GitLab.GfmAutoComplete.setup();
app/views/notes/_create_discussion_note.js.haml
1 - if note.valid? 1 - if note.valid?
2 :plain 2 :plain
3 NoteList.appendNewDiscussionNote("#{note.discussion_id}", 3 NoteList.appendNewDiscussionNote("#{note.discussion_id}",
4 - "#{escape_javascript(render "notes/diff_notes_with_reply", notes: [note])}",  
5 - "#{escape_javascript(render "notes/note", note: note)}"); 4 + "#{escape_javascript(render "notes/diff_notes_with_reply", notes: [note])}",
  5 + "#{escape_javascript(render "notes/note", note: note)}");
app/views/notes/_discussion_note_form.html.haml
@@ -10,7 +10,7 @@ @@ -10,7 +10,7 @@
10 - @note.errors.full_messages.each do |msg| 10 - @note.errors.full_messages.each do |msg|
11 %div= msg 11 %div= msg
12 12
13 - = f.text_area :note, size: 255, class: 'js-note-text js-gfm-input' 13 + = f.text_area :note, size: 255, class: 'note_text js-note-text js-gfm-input'
14 .note_actions 14 .note_actions
15 .buttons 15 .buttons
16 = f.submit 'Add Comment', class: "btn comment-btn js-comment-button" 16 = f.submit 'Add Comment', class: "btn comment-btn js-comment-button"
app/views/notes/_notes_with_form.html.haml
1 %ul#notes-list.notes 1 %ul#notes-list.notes
  2 +.notes-status
2 3
3 - if can? current_user, :write_note, @project 4 - if can? current_user, :write_note, @project
4 - .note-forms.js-note-forms 5 + #note-forms.js-note-forms
5 = render "notes/common_form" 6 = render "notes/common_form"
6 = render "notes/discussion_note_form" 7 = render "notes/discussion_note_form"
7 8