Commit 140652e9b019addaf7022e18b6816ecb36eee80c
1 parent
5d3fb35c
Exists in
master
and in
4 other branches
Fix common form and note preview
Showing
8 changed files
with
122 additions
and
107 deletions
Show diff stats
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