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