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,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 |