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 10 reversed: false,
11 11  
12 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 23 textarea.css("height", "40px");
23 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 30 // get initial set of notes
30   - this.getContent();
  31 + NoteList.getContent();
31 32  
32 33 disableButtonIfEmptyField(".js-note-text", ".js-comment-button");
33 34  
... ... @@ -37,34 +38,21 @@ var NoteList = {
37 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 42 $(document).on("click",
60 43 ".js-add-diff-note-button",
61 44 NoteList.addDiffNote);
62 45  
63   - // reply to diff notes
  46 + // reply to diff/discussion notes
64 47 $(document).on("click",
65 48 ".js-discussion-reply-button",
66 49 NoteList.replyToDiscussionNote);
67 50  
  51 + // setup note preview
  52 + $(document).on("click",
  53 + ".js-note-preview-button",
  54 + NoteList.previewNote);
  55 +
68 56 // hide diff note form
69 57 $(document).on("click",
70 58 ".js-close-discussion-note-form",
... ... @@ -83,8 +71,12 @@ var NoteList = {
83 71  
84 72 // clean up previews for forms
85 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 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 144 * Called in response to deleting a note on a diff line.
128 145 *
129 146 * Removes the actual note from view.
... ... @@ -233,8 +250,8 @@ var NoteList = {
233 250 */
234 251 getContent: function() {
235 252 $.ajax({
236   - url: this.notes_path,
237   - data: this.target_params,
  253 + url: NoteList.notes_path,
  254 + data: NoteList.target_params,
238 255 complete: function(){ $('.notes-status').removeClass("loading")},
239 256 beforeSend: function() { $('.notes-status').addClass("loading") },
240 257 dataType: "script"
... ... @@ -246,23 +263,23 @@ var NoteList = {
246 263 * Replaces the content of #notes-list with the given html.
247 264 */
248 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 268 $("#notes-list").html(html);
252 269  
253   - if (this.reversed) {
  270 + if (NoteList.reversed) {
254 271 // init infinite scrolling
255   - this.initLoadMore();
  272 + NoteList.initLoadMore();
256 273  
257 274 // init getting new notes
258   - this.initRefreshNew();
  275 + NoteList.initRefreshNew();
259 276 }
260 277 },
261 278  
262 279  
263 280 /**
264 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 284 * Set up refreshing only new notes after all notes have been loaded.
268 285 */
... ... @@ -292,8 +309,8 @@ var NoteList = {
292 309 // only load more notes if there are no "new" notes
293 310 $('.loading').show();
294 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 314 complete: function(){ $('.notes-status').removeClass("loading")},
298 315 beforeSend: function() { $('.notes-status').addClass("loading") },
299 316 dataType: "script"
... ... @@ -306,8 +323,8 @@ var NoteList = {
306 323 */
307 324 appendMoreNotes: function(newNoteIds, html) {
308 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 328 $("#notes-list").append(html);
312 329 }
313 330 },
... ... @@ -315,17 +332,12 @@ var NoteList = {
315 332 /**
316 333 * Called in response to getMore().
317 334 * Disables loading more notes when scrolling to the bottom of the page.
318   - * Initalizes refreshing new notes.
319 335 */
320 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 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 346 *
335 347 * New notes are all notes that are created after the site has been loaded.
336 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 362 */
351 363 getNew: function() {
352 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 367 dataType: "script"
356 368 });
357 369 },
... ... @@ -362,21 +374,20 @@ var NoteList = {
362 374 */
363 375 replaceNewNotes: function(newNoteIds, html) {
364 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 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 391 appendNewDiscussionNote: function(discussionId, diffRowHtml, noteHtml) {
381 392 // is this the first note of discussion?
382 393 var row = $("form[rel='"+discussionId+"']").closest("tr");
... ... @@ -401,7 +412,7 @@ var NoteList = {
401 412 */
402 413 updateVotes: function() {
403 414 var votes = $("#votes .votes");
404   - var notes = $("#notes-list").find(".note .vote");
  415 + var notes = $("#notes-list .note .vote");
405 416  
406 417 // only update if there is a vote display
407 418 if (votes.size()) {
... ...
app/assets/stylesheets/behaviors.scss
... ... @@ -8,7 +8,7 @@
8 8  
9 9 // Toggler
10 10 //--------
11   -.js-toggler-container .turn-on { display: inline-block; }
  11 +.js-toggler-container .turn-on { display: inherit; }
12 12 .js-toggler-container .turn-off { display: none; }
13 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 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 321 border: 1px solid #aaa;
315   - box-shadow:none;
  322 + box-shadow: none;
316 323 }
317 324 // TODO: end cleanup
318 325 }
319 326  
320 327 // hide the new discussion note form template
321   -.note-forms {
  328 +#note-forms {
  329 + .note-form-holder {
  330 + margin-top: 5px;
  331 + }
322 332 .new_discussion_note {
323 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 11 - @note.errors.full_messages.each do |msg|
12 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 20 .clearfix
19 21  
20   - .row.note_advanced_opts
21   - .span3
  22 + .buttons
22 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 40 %h6.left Notify via email:
26 41 = label_tag :notify do
27 42 = check_box_tag :notify, 1, @note.noteable_type != "Commit"
... ... @@ -31,11 +46,4 @@
31 46 = label_tag :notify_author do
32 47 = check_box_tag :notify_author, 1 , @note.noteable_type == "Commit"
33 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 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 2 NoteList.appendNewNote(#{note.id}, "#{escape_javascript(render "notes/note", note: note)}");
9 3  
10 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 1 - if note.valid?
2 2 :plain
3 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 10 - @note.errors.full_messages.each do |msg|
11 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 14 .note_actions
15 15 .buttons
16 16 = f.submit 'Add Comment', class: "btn comment-btn js-comment-button"
... ...
app/views/notes/_notes_with_form.html.haml
1 1 %ul#notes-list.notes
  2 +.notes-status
2 3  
3 4 - if can? current_user, :write_note, @project
4   - .note-forms.js-note-forms
  5 + #note-forms.js-note-forms
5 6 = render "notes/common_form"
6 7 = render "notes/discussion_note_form"
7 8  
... ...