Commit 6fc10fa2564538bb892090759fdb05604b0e5567

Authored by Riyad Preukschas
1 parent fbd345ea

Unify forms for discussions and main target.

Allows previews and uploads in all forms.
Also fixes #1730
app/assets/javascripts/notes.js
@@ -16,22 +16,22 @@ var NoteList = { @@ -16,22 +16,22 @@ var NoteList = {
16 NoteList.reversed = $("#notes-list").is(".reversed"); 16 NoteList.reversed = $("#notes-list").is(".reversed");
17 NoteList.target_params = "target_type=" + NoteList.target_type + "&target_id=" + NoteList.target_id; 17 NoteList.target_params = "target_type=" + NoteList.target_type + "&target_id=" + NoteList.target_id;
18 18
  19 + NoteList.setupMainTargetNoteForm();
  20 +
19 if(NoteList.reversed) { 21 if(NoteList.reversed) {
20 - var form = $("#new_note");  
21 - form.find(".buttons, .note_advanced_opts").hide(); 22 + var form = $(".js-main-target-form");
  23 + form.find(".buttons, .note_options").hide();
22 var textarea = form.find(".js-note-text"); 24 var textarea = form.find(".js-note-text");
23 textarea.css("height", "40px"); 25 textarea.css("height", "40px");
24 textarea.on("focus", function(){ 26 textarea.on("focus", function(){
25 textarea.css("height", "80px"); 27 textarea.css("height", "80px");
26 - form.find(".buttons, .note_advanced_opts").show(); 28 + form.find(".buttons, .note_options").show();
27 }); 29 });
28 } 30 }
29 31
30 // get initial set of notes 32 // get initial set of notes
31 NoteList.getContent(); 33 NoteList.getContent();
32 34
33 - disableButtonIfEmptyField(".js-note-text", ".js-comment-button");  
34 -  
35 $("#note_attachment").change(function(e){ 35 $("#note_attachment").change(function(e){
36 var val = $('.input-file').val(); 36 var val = $('.input-file').val();
37 var filename = val.replace(/^.*[\\\/]/, ''); 37 var filename = val.replace(/^.*[\\\/]/, '');
@@ -70,10 +70,7 @@ var NoteList = { @@ -70,10 +70,7 @@ var NoteList = {
70 NoteList.removeNote); 70 NoteList.removeNote);
71 71
72 // clean up previews for forms 72 // clean up previews for forms
73 - $(document).on("ajax:complete", ".note-form-holder", function(){  
74 - //$(this).find('.js-note-preview-button').text('Preview');  
75 - //$(this).find('.js-note-preview').hide();  
76 - 73 + $(document).on("ajax:complete", ".js-main-target-form", function(){
77 $(this).find('.error').remove(); 74 $(this).find('.error').remove();
78 $(this).find('.js-note-text').val(""); 75 $(this).find('.js-note-text').val("");
79 $(this).show(); 76 $(this).show();
@@ -93,8 +90,10 @@ var NoteList = { @@ -93,8 +90,10 @@ var NoteList = {
93 * Sets up the form and shows it. 90 * Sets up the form and shows it.
94 */ 91 */
95 addDiffNote: function(e) { 92 addDiffNote: function(e) {
  93 + e.preventDefault();
  94 +
96 // find the form 95 // find the form
97 - var form = $(".js-note-forms .js-discussion-note-form"); 96 + var form = $(".js-new-note-form");
98 var row = $(this).closest("tr"); 97 var row = $(this).closest("tr");
99 var nextRow = row.next(); 98 var nextRow = row.next();
100 99
@@ -111,8 +110,6 @@ var NoteList = { @@ -111,8 +110,6 @@ var NoteList = {
111 // show the form 110 // show the form
112 NoteList.setupDiscussionNoteForm($(this), row.next().find("form")); 111 NoteList.setupDiscussionNoteForm($(this), row.next().find("form"));
113 } 112 }
114 -  
115 - e.preventDefault();  
116 }, 113 },
117 114
118 /** 115 /**
@@ -123,21 +120,23 @@ var NoteList = { @@ -123,21 +120,23 @@ var NoteList = {
123 * Note: uses the Toggler behavior to toggle preview/edit views/buttons 120 * Note: uses the Toggler behavior to toggle preview/edit views/buttons
124 */ 121 */
125 previewNote: function(e) { 122 previewNote: function(e) {
  123 + e.preventDefault();
  124 +
126 var form = $(this).closest("form"); 125 var form = $(this).closest("form");
127 var preview = form.find('.js-note-preview'); 126 var preview = form.find('.js-note-preview');
128 - var note_text = form.find('.js-note-text').val(); 127 + var noteText = form.find('.js-note-text').val();
  128 +
  129 + console.log("preview", noteText);
129 130
130 - if(note_text.trim().length === 0) { 131 + if(noteText.trim().length === 0) {
131 preview.text('Nothing to preview.'); 132 preview.text('Nothing to preview.');
132 - } else if($(this).data('url')) { 133 + } else {
133 preview.text('Loading...'); 134 preview.text('Loading...');
134 - $.post($(this).data('url'), {note: note_text}) 135 + $.post($(this).data('url'), {note: noteText})
135 .success(function(previewData) { 136 .success(function(previewData) {
136 preview.html(previewData); 137 preview.html(previewData);
137 }); 138 });
138 } 139 }
139 -  
140 - e.preventDefault();  
141 }, 140 },
142 141
143 /** 142 /**
@@ -168,6 +167,8 @@ var NoteList = { @@ -168,6 +167,8 @@ var NoteList = {
168 * Removes the form and if necessary it's temporary row. 167 * Removes the form and if necessary it's temporary row.
169 */ 168 */
170 removeDiscussionNoteForm: function(e) { 169 removeDiscussionNoteForm: function(e) {
  170 + e.preventDefault();
  171 +
171 var form = $(this).closest("form"); 172 var form = $(this).closest("form");
172 var row = form.closest("tr"); 173 var row = form.closest("tr");
173 174
@@ -181,8 +182,6 @@ var NoteList = { @@ -181,8 +182,6 @@ var NoteList = {
181 // only remove the form 182 // only remove the form
182 form.remove(); 183 form.remove();
183 } 184 }
184 -  
185 - e.preventDefault();  
186 }, 185 },
187 186
188 /** 187 /**
@@ -202,7 +201,7 @@ var NoteList = { @@ -202,7 +201,7 @@ var NoteList = {
202 */ 201 */
203 replyToDiscussionNote: function() { 202 replyToDiscussionNote: function() {
204 // find the form 203 // find the form
205 - var form = $(".js-note-forms .js-discussion-note-form"); 204 + var form = $(".js-new-note-form");
206 205
207 // hide reply button 206 // hide reply button
208 $(this).hide(); 207 $(this).hide();
@@ -213,27 +212,83 @@ var NoteList = { @@ -213,27 +212,83 @@ var NoteList = {
213 NoteList.setupDiscussionNoteForm($(this), $(this).next("form")); 212 NoteList.setupDiscussionNoteForm($(this), $(this).next("form"));
214 }, 213 },
215 214
  215 +
  216 + /**
  217 + * Helper for inserting and setting up note forms.
  218 + */
  219 +
  220 +
216 /** 221 /**
217 - * Shows the diff line form and does some setup. 222 + * Shows the diff/discussion form and does some setup on it.
218 * 223 *
219 * Sets some hidden fields in the form. 224 * Sets some hidden fields in the form.
220 * 225 *
221 - * Note: "this" must have the "discussionId", "lineCode", "noteableType" and  
222 - * "noteableId" data attributes set. 226 + * Note: dataHolder must have the "discussionId", "lineCode", "noteableType"
  227 + * and "noteableId" data attributes set.
223 */ 228 */
224 - setupDiscussionNoteForm: function(data_holder, form) { 229 + setupDiscussionNoteForm: function(dataHolder, form) {
225 // setup note target 230 // setup note target
226 - form.attr("rel", data_holder.data("discussionId"));  
227 - form.find("#note_line_code").val(data_holder.data("lineCode"));  
228 - form.find("#note_noteable_type").val(data_holder.data("noteableType"));  
229 - form.find("#note_noteable_id").val(data_holder.data("noteableId")); 231 + form.attr("rel", dataHolder.data("discussionId"));
  232 + form.find("#note_line_code").val(dataHolder.data("lineCode"));
  233 + form.find("#note_noteable_type").val(dataHolder.data("noteableType"));
  234 + form.find("#note_noteable_id").val(dataHolder.data("noteableId"));
230 235
231 - // setup interaction  
232 - disableButtonIfEmptyField(form.find(".js-note-text"), form.find(".js-comment-button"));  
233 - GitLab.GfmAutoComplete.setup(); 236 + NoteList.setupNoteForm(form);
234 237
235 - // cleanup after successfully creating a diff note 238 + // cleanup after successfully creating a diff/discussion note
236 form.on("ajax:success", NoteList.removeDiscussionNoteForm); 239 form.on("ajax:success", NoteList.removeDiscussionNoteForm);
  240 + },
  241 +
  242 + /**
  243 + * Shows the main form and does some setup on it.
  244 + *
  245 + * Sets some hidden fields in the form.
  246 + */
  247 + setupMainTargetNoteForm: function() {
  248 + // find the form
  249 + var form = $(".js-new-note-form");
  250 + // insert the form after the button
  251 + form.clone().replaceAll($(".js-main-target-form"));
  252 +
  253 + form = form.prev("form");
  254 +
  255 + // show the form
  256 + NoteList.setupNoteForm(form);
  257 +
  258 + // fix classes
  259 + form.removeClass("js-new-note-form");
  260 + form.addClass("js-main-target-form");
  261 +
  262 + // remove unnecessary fields and buttons
  263 + form.find("#note_line_code").remove();
  264 + form.find(".js-close-discussion-note-form").remove();
  265 + },
  266 +
  267 + /**
  268 + * General note form setup.
  269 + *
  270 + * * deactivates the submit button when text is empty
  271 + * * hides the preview button when text is empty
  272 + * * setup GFM auto complete
  273 + * * show the form
  274 + */
  275 + setupNoteForm: function(form) {
  276 + disableButtonIfEmptyField(form.find(".js-note-text"), form.find(".js-comment-button"));
  277 +
  278 + // setup preview buttons
  279 + $(".js-note-edit-button, .js-note-preview-button").tooltip({ placement: 'left' });
  280 +
  281 + previewButton = $(".js-note-preview-button");
  282 + previewButton.hide();
  283 + form.find(".js-note-text").on("input", function() {
  284 + if ($(this).val().trim() !== "") {
  285 + previewButton.fadeIn();
  286 + } else {
  287 + previewButton.fadeOut();
  288 + }
  289 + });
  290 +
  291 + GitLab.GfmAutoComplete.setup();
237 292
238 form.show(); 293 form.show();
239 }, 294 },
app/assets/stylesheets/sections/notes.scss
@@ -239,46 +239,51 @@ p.notify_controls span{ @@ -239,46 +239,51 @@ p.notify_controls span{
239 .reply-btn { 239 .reply-btn {
240 @extend .save-btn; 240 @extend .save-btn;
241 } 241 }
242 -.new_discussion_note {  
243 - // hide it by default 242 +.diff_file,
  243 +.discussion {
  244 + .new_note {
  245 + margin: 8px 5px 8px 0;
  246 + }
  247 +}
  248 +.new_note {
244 display: none; 249 display: none;
245 - margin: 8px 5px 8px 0;  
246 250
247 - // TODO: start cleanup  
248 - .note_actions {  
249 - margin:0;  
250 - padding-top: 10px; 251 + .buttons {
  252 + float: left;
  253 + margin-top: 8px;
  254 + }
  255 + .note_options {
  256 + h6 {
  257 + line-height: 32px;
  258 + padding-right: 15px;
  259 + }
  260 + }
  261 + .note_text_and_preview {
  262 + // makes the "absolute" position for links relative to this
  263 + position: relative;
251 264
252 - .buttons {  
253 - float:left;  
254 - width:300px; 265 + // preview/edit buttons
  266 + > a {
  267 + font-size: 24px;
  268 + padding: 4px;
  269 + position: absolute;
  270 + right: 0;
255 } 271 }
256 - .options {  
257 - .labels {  
258 - float:left;  
259 - padding-left:10px;  
260 - label {  
261 - padding: 6px 0;  
262 - margin: 0;  
263 - width:120px;  
264 - }  
265 - } 272 + .note_preview {
  273 + background: #f5f5f5;
  274 + border: 1px solid #ddd;
  275 + @include border-radius(4px);
  276 + min-height: 80px;
  277 + padding: 4px 6px;
  278 + }
  279 + .note_text {
  280 + font-size: 14px;
  281 + height: 80px;
  282 + width: 98.6%;
266 } 283 }
267 - }  
268 - // TODO: end cleanup  
269 -}  
270 -.new_note {  
271 - textarea {  
272 - height:80px;  
273 - width:99%;  
274 - font-size:14px;  
275 } 284 }
276 285
277 // TODO: start cleanup 286 // TODO: start cleanup
278 - .attach_holder {  
279 - display:none;  
280 - }  
281 -  
282 .attachments { 287 .attachments {
283 position: relative; 288 position: relative;
284 width: 350px; 289 width: 350px;
@@ -316,32 +321,5 @@ p.notify_controls span{ @@ -316,32 +321,5 @@ p.notify_controls span{
316 padding:0; 321 padding:0;
317 margin: 0; 322 margin: 0;
318 } 323 }
319 - .note_advanced_opts {  
320 - h6 {  
321 - line-height: 32px;  
322 - padding-right: 15px;  
323 - }  
324 - }  
325 - .note_preview {  
326 - margin: 2px;  
327 - border: 1px solid #ddd;  
328 - padding: 10px;  
329 - min-height: 60px;  
330 - background:#f5f5f5;  
331 - }  
332 - .note_text {  
333 - border: 1px solid #aaa;  
334 - box-shadow: none;  
335 - }  
336 // TODO: end cleanup 324 // TODO: end cleanup
337 } 325 }
338 -  
339 -// hide the new discussion note form template  
340 -#note-forms {  
341 - .note-form-holder {  
342 - margin-top: 5px;  
343 - }  
344 - .new_discussion_note {  
345 - display: none;  
346 - }  
347 -}  
app/views/notes/_common_form.html.haml
1 -.note-form-holder  
2 - = form_for [@project, @note], remote: "true", multipart: true do |f|  
3 -  
4 - = note_target_fields  
5 - = f.hidden_field :noteable_id  
6 - = f.hidden_field :noteable_type  
7 -  
8 - %h3.page_title Leave a comment  
9 - -if @note.errors.any?  
10 - .alert-message.block-message.error  
11 - - @note.errors.full_messages.each do |msg|  
12 - %div= msg  
13 -  
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'}.  
20 - .clearfix  
21 -  
22 - .buttons  
23 - = f.submit 'Add Comment', class: "btn comment-btn grouped js-comment-button"  
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  
40 - %h6.left Notify via email:  
41 - = label_tag :notify do  
42 - = check_box_tag :notify, 1, @note.noteable_type != "Commit"  
43 - %span Project team  
44 -  
45 - - if @note.notify_only_author?(current_user)  
46 - = label_tag :notify_author do  
47 - = check_box_tag :notify_author, 1 , @note.noteable_type == "Commit"  
48 - %span Commit author 1 += form_for [@project, @note], remote: true, html: { multipart: true, id: nil, class: "new_note js-new-note-form" } do |f|
  2 +
  3 + = note_target_fields
  4 + = f.hidden_field :line_code
  5 + = f.hidden_field :noteable_id
  6 + = f.hidden_field :noteable_type
  7 +
  8 + - if @note.errors.any?
  9 + .alert-message.block-message.error
  10 + - @note.errors.full_messages.each do |msg|
  11 + %div= msg
  12 +
  13 + .note_text_and_preview.js-toggler-container
  14 + %a.js-note-preview-button.js-toggler-target.turn-on{ href: "javascript:;", data: {title: "Preview", url: preview_project_notes_path(@project)} }
  15 + %i.icon-eye-open
  16 + %a.js-note-edit-button.js-toggler-target.turn-off{ href: "javascript:;", data: {title: "Edit"} }
  17 + %i.icon-edit
  18 +
  19 + = f.text_area :note, size: 255, class: 'note_text js-note-text js-gfm-input turn-on'
  20 + .note_preview.js-note-preview.turn-off
  21 +
  22 + .buttons
  23 + = f.submit 'Add Comment', class: "btn comment-btn grouped js-comment-button"
  24 + %a.btn.grouped.js-close-discussion-note-form Cancel
  25 + .hint
  26 + .right Comments are parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}.
  27 + .clearfix
  28 +
  29 + .note_options
  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
  40 + %h6.left Notify via email:
  41 + = label_tag :notify do
  42 + = check_box_tag :notify, 1, !@note.for_commit?
  43 + %span Project team
  44 +
  45 + - if @note.notify_only_author?(current_user)
  46 + = label_tag :notify_author do
  47 + = check_box_tag :notify_author, 1 , !@note.for_commit?
  48 + %span Commit author
49 .clearfix 49 .clearfix
app/views/notes/_create_common_note.js.haml
@@ -5,5 +5,6 @@ @@ -5,5 +5,6 @@
5 NoteList.appendNewNote(#{note.id}, "#{escape_javascript(render "notes/note", note: note)}"); 5 NoteList.appendNewNote(#{note.id}, "#{escape_javascript(render "notes/note", note: note)}");
6 6
7 - else 7 - else
8 - $(".note-form-holder").replaceWith("#{escape_javascript(render 'notes/common_form')}"); 8 + -# TODO: insert form correctly
  9 + $(".js-main-target-note").replaceWith("#{escape_javascript(render 'notes/common_form')}");
9 GitLab.GfmAutoComplete.setup(); 10 GitLab.GfmAutoComplete.setup();
app/views/notes/_discussion_note_form.html.haml
@@ -1,28 +0,0 @@ @@ -1,28 +0,0 @@
1 -= form_for [@project, @note], remote: true, html: { multipart: true, class: "new_note new_discussion_note js-discussion-note-form" } do |f|  
2 -  
3 - = note_target_fields  
4 - = f.hidden_field :line_code  
5 - = f.hidden_field :noteable_id  
6 - = f.hidden_field :noteable_type  
7 -  
8 - -if @note.errors.any?  
9 - .alert-message.block-message.error  
10 - - @note.errors.full_messages.each do |msg|  
11 - %div= msg  
12 -  
13 - = f.text_area :note, size: 255, class: 'note_text js-note-text js-gfm-input'  
14 - .note_actions  
15 - .buttons  
16 - = f.submit 'Add Comment', class: "btn comment-btn js-comment-button"  
17 - %button.btn.js-close-discussion-note-form Cancel  
18 - .options  
19 - %h6.left Notify via email:  
20 - .labels  
21 - = label_tag :notify do  
22 - = check_box_tag :notify, 1, @note.noteable_type != "Commit"  
23 - %span Project team  
24 -  
25 - - if @note.notify_only_author?(current_user)  
26 - = label_tag :notify_author do  
27 - = check_box_tag :notify_author, 1 , @note.noteable_type == "Commit"  
28 - %span Commit author  
app/views/notes/_notes_with_form.html.haml
1 %ul#notes-list.notes 1 %ul#notes-list.notes
2 .notes-status 2 .notes-status
3 3
  4 +.js-main-target-form
4 - if can? current_user, :write_note, @project 5 - if can? current_user, :write_note, @project
5 - #note-forms.js-note-forms  
6 - = render "notes/common_form"  
7 - = render "notes/discussion_note_form" 6 + = render "notes/common_form"
8 7
9 :javascript 8 :javascript
10 $(function(){ 9 $(function(){
app/views/notes/_reversed_notes_with_form.html.haml
  1 +.js-main-target-form
1 - if can? current_user, :write_note, @project 2 - if can? current_user, :write_note, @project
2 = render "notes/common_form" 3 = render "notes/common_form"
3 4