From fc1c250d404902c9b34ccd28d9cfea7108f80831 Mon Sep 17 00:00:00 2001 From: Riyad Preukschas Date: Mon, 29 Oct 2012 15:49:37 +0100 Subject: Reorder Note methods and add helpers --- app/models/note.rb | 85 +++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 58 insertions(+), 27 deletions(-) diff --git a/app/models/note.rb b/app/models/note.rb index da15a173566..6708fbc3758 100644 --- a/app/models/note.rb +++ b/app/models/note.rb @@ -18,7 +18,6 @@ require 'carrierwave/orm/activerecord' require 'file_size_validator' class Note < ActiveRecord::Base - attr_accessible :note, :noteable, :noteable_id, :noteable_type, :project_id, :attachment, :line_code @@ -55,12 +54,58 @@ class Note < ActiveRecord::Base }, without_protection: true) end - def notify - @notify ||= false + def commit_author + @commit_author ||= + project.users.find_by_email(noteable.author_email) || + project.users.find_by_name(noteable.author_name) + rescue + nil end - def notify_author - @notify_author ||= false + def diff + noteable.diffs[diff_file_index] + end + + def diff_file_index + line_code.split('_')[0].to_i + end + + def diff_file_name + diff.b_path + end + + def diff_new_line + line_code.split('_')[2].to_i + end + + def discussion_id + @discussion_id ||= [noteable_type, noteable_id, line_code].join.underscore.to_sym + end + + # Returns true if this is a downvote note, + # otherwise false is returned + def downvote? + note.start_with?('-1') || note.start_with?(':-1:') + end + + def for_commit? + noteable_type == "Commit" + end + + def for_commit_diff_line? + for_commit? && for_diff_line? + end + + def for_diff_line? + line_code.present? + end + + def for_merge_request? + noteable_type == "MergeRequest" + end + + def for_merge_request_diff_line? + for_merge_request? && for_diff_line? end # override to return commits, which are not active record @@ -76,6 +121,14 @@ class Note < ActiveRecord::Base nil end + def notify + @notify ||= false + end + + def notify_author + @notify_author ||= false + end + # Check if we can notify commit author # with email about our comment # @@ -94,31 +147,9 @@ class Note < ActiveRecord::Base commit_author.email != user.email end - def for_commit? - noteable_type == "Commit" - end - - def for_diff_line? - line_code.present? - end - - def commit_author - @commit_author ||= - project.users.find_by_email(noteable.author_email) || - project.users.find_by_name(noteable.author_name) - rescue - nil - end - # Returns true if this is an upvote note, # otherwise false is returned def upvote? note.start_with?('+1') || note.start_with?(':+1:') end - - # Returns true if this is a downvote note, - # otherwise false is returned - def downvote? - note.start_with?('-1') || note.start_with?(':-1:') - end end -- cgit v1.2.1 From b91d6802572eeb152bd86dd68c54ef4151180848 Mon Sep 17 00:00:00 2001 From: Riyad Preukschas Date: Mon, 29 Oct 2012 15:50:30 +0100 Subject: Fix notes helper --- app/helpers/notes_helper.rb | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/app/helpers/notes_helper.rb b/app/helpers/notes_helper.rb index ffcc7acc8da..5cada379c3c 100644 --- a/app/helpers/notes_helper.rb +++ b/app/helpers/notes_helper.rb @@ -9,16 +9,13 @@ module NotesHelper # Helps to distinguish e.g. commit notes in mr notes list def note_for_main_target?(note) - !@mixed_targets || @main_target_type == note.noteable_type + !@mixed_targets || (@main_target_type == note.noteable_type && !note.for_diff_line?) end def link_to_commit_diff_line_note(note) - commit = note.noteable - diff_index, diff_old_line, diff_new_line = note.line_code.split('_') + if note.for_commit_diff_line? + link_to "#{note.diff_file_name}:L#{note.diff_new_line}", project_commit_path(@project, note.noteable, anchor: note.line_code) + end - link_file = commit.diffs[diff_index.to_i].new_path - link_line = diff_new_line - - link_to "#{link_file}:L#{link_line}", project_commit_path(@project, commit, anchor: note.line_code) end end -- cgit v1.2.1 From 9b919939a35f9e5606f86a09eafa2a392d40d1a7 Mon Sep 17 00:00:00 2001 From: Riyad Preukschas Date: Mon, 29 Oct 2012 15:55:37 +0100 Subject: Fix parameter passing and wording for per line notes --- app/controllers/commit_controller.rb | 4 +++- app/controllers/merge_requests_controller.rb | 4 +++- app/views/commits/_text_file.html.haml | 2 +- app/views/merge_requests/_show.html.haml | 4 ++-- app/views/notes/_create_per_line_note.js.haml | 2 +- app/views/notes/_per_line_form.html.haml | 4 ++-- app/views/notes/_per_line_note_link.html.haml | 7 ++++++- app/views/notes/_per_line_notes_with_reply.html.haml | 2 +- app/views/notes/_per_line_reply_button.html.haml | 10 ++++++++-- 9 files changed, 27 insertions(+), 12 deletions(-) diff --git a/app/controllers/commit_controller.rb b/app/controllers/commit_controller.rb index d671e9f9e9e..ebc27772f9a 100644 --- a/app/controllers/commit_controller.rb +++ b/app/controllers/commit_controller.rb @@ -17,7 +17,9 @@ class CommitController < ProjectResourceController @note = result[:note] @line_notes = result[:line_notes] @notes_count = result[:notes_count] - @comments_allowed = true + @comments_allowed = @reply_allowed = true + @comments_target = { noteable_type: 'Commit', + noteable_id: @commit.id } respond_to do |format| format.html do diff --git a/app/controllers/merge_requests_controller.rb b/app/controllers/merge_requests_controller.rb index 362962707fd..24f4239e520 100644 --- a/app/controllers/merge_requests_controller.rb +++ b/app/controllers/merge_requests_controller.rb @@ -34,7 +34,9 @@ class MergeRequestsController < ProjectResourceController @diffs = @merge_request.diffs @commit = @merge_request.last_commit - @comments_allowed = true + @comments_allowed = @reply_allowed = true + @comments_target = { noteable_type: 'MergeRequest', + noteable_id: @merge_request.id } @line_notes = @merge_request.notes.where("line_code is not null") end diff --git a/app/views/commits/_text_file.html.haml b/app/views/commits/_text_file.html.haml index 02117386d71..5e7886922b4 100644 --- a/app/views/commits/_text_file.html.haml +++ b/app/views/commits/_text_file.html.haml @@ -17,7 +17,7 @@ %td.new_line= link_to raw(type == "old" ? " " : line_new) , "##{line_code}", id: line_code %td.line_content{class: "noteable_line #{type} #{line_code}", "line_code" => line_code}= raw "#{line}  " - - if @comments_allowed + - if @reply_allowed - comments = @line_notes.select { |n| n.line_code == line_code }.sort_by(&:created_at) - unless comments.empty? = render "notes/per_line_notes_with_reply", notes: comments diff --git a/app/views/merge_requests/_show.html.haml b/app/views/merge_requests/_show.html.haml index f1d0c8aaafb..d12431da70b 100644 --- a/app/views/merge_requests/_show.html.haml +++ b/app/views/merge_requests/_show.html.haml @@ -7,11 +7,11 @@ - if @commits.present? %ul.nav.nav-tabs.mr_nav_tabs %li - = link_to "#notes", "data-url" => project_merge_request_path(@project, @merge_request), class: "merge-notes-tab tab" do + = link_to "#notes", title: "Comments", "data-url" => project_merge_request_path(@project, @merge_request), class: "merge-notes-tab tab" do %i.icon-comment Comments %li - = link_to "#diffs", "data-url" => diffs_project_merge_request_path(@project, @merge_request), class: "merge-diffs-tab tab" do + = link_to "#diffs", title: "Diff", "data-url" => diffs_project_merge_request_path(@project, @merge_request), class: "merge-diffs-tab tab" do %i.icon-list-alt Diff diff --git a/app/views/notes/_create_per_line_note.js.haml b/app/views/notes/_create_per_line_note.js.haml index 180960e38e4..eea9eb38be4 100644 --- a/app/views/notes/_create_per_line_note.js.haml +++ b/app/views/notes/_create_per_line_note.js.haml @@ -11,7 +11,7 @@ // find the commented line ... var trEl = $(".#{note.line_code}").parent(); // ... and insert the note and the reply button after it - trEl.after("#{escape_javascript(render "notes/per_line_reply_button", line_code: note.line_code)}"); + trEl.after("#{escape_javascript(render "notes/per_line_reply_button", note: note)}"); trEl.after("#{escape_javascript(render "notes/per_line_note", note: note)}"); } else { // instert new note before reply button diff --git a/app/views/notes/_per_line_form.html.haml b/app/views/notes/_per_line_form.html.haml index c8d79850162..460d49522bf 100644 --- a/app/views/notes/_per_line_form.html.haml +++ b/app/views/notes/_per_line_form.html.haml @@ -3,7 +3,7 @@ %td{colspan: 3 } .line-note-form-holder = form_for [@project, @note], remote: "true", multipart: true do |f| - %h3.page_title Leave a note + %h3.page_title Leave a comment %div.span10 -if @note.errors.any? .alert-message.block-message.error @@ -16,7 +16,7 @@ = f.text_area :note, size: 255, class: 'line-note-text js-gfm-input' .note_actions .buttons - = f.submit 'Add note', class: "btn save-btn submit_note submit_inline_note", id: "submit_note" + = f.submit 'Add Comment', class: "btn save-btn submit_note submit_inline_note", id: "submit_note" = link_to "Cancel", "#", class: "btn hide-button" .options %h6.left Notify via email: diff --git a/app/views/notes/_per_line_note_link.html.haml b/app/views/notes/_per_line_note_link.html.haml index 72b59a596a3..16db3d809cb 100644 --- a/app/views/notes/_per_line_note_link.html.haml +++ b/app/views/notes/_per_line_note_link.html.haml @@ -1 +1,6 @@ -= link_to "", "#", class: "line_note_link", data: { line_code: line_code }, title: "Add note for this line" += link_to "", + "#", + id: "line-note-#{line_code}", + class: "line_note_link", + data: @comments_target.merge({ line_code: line_code }), + title: "Add comment on line #{line_code[/[0-9]+$/]}" diff --git a/app/views/notes/_per_line_notes_with_reply.html.haml b/app/views/notes/_per_line_notes_with_reply.html.haml index 1bcfc41fe20..ebe0c5c6c47 100644 --- a/app/views/notes/_per_line_notes_with_reply.html.haml +++ b/app/views/notes/_per_line_notes_with_reply.html.haml @@ -1,3 +1,3 @@ - notes.each do |note| = render "notes/per_line_note", note: note -= render "notes/per_line_reply_button", line_code: notes.first.line_code += render "notes/per_line_reply_button", note: notes.first diff --git a/app/views/notes/_per_line_reply_button.html.haml b/app/views/notes/_per_line_reply_button.html.haml index 42c737c75ae..c9d2696675e 100644 --- a/app/views/notes/_per_line_reply_button.html.haml +++ b/app/views/notes/_per_line_reply_button.html.haml @@ -1,4 +1,10 @@ %tr.line_notes_row.reply %td{colspan: 3} - %i.icon-comment - = link_to "Reply", "#", class: "line_note_reply_link", data: { line_code: line_code }, title: "Add note for this line" + = link_to "#", + class: "line_note_reply_link", + data: { line_code: note.line_code, + noteable_type: note.noteable_type, + noteable_id: note.noteable_id }, + title: "Add note for this line" do + %i.icon-comment + Reply -- cgit v1.2.1 From a58385247d06b238296e35c17c9e3f58b3234094 Mon Sep 17 00:00:00 2001 From: Riyad Preukschas Date: Mon, 29 Oct 2012 15:56:17 +0100 Subject: Add discussions for merge requests to notes controller --- app/controllers/notes_controller.rb | 39 +++++++++++++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/app/controllers/notes_controller.rb b/app/controllers/notes_controller.rb index d794f368f57..79e8bcc7866 100644 --- a/app/controllers/notes_controller.rb +++ b/app/controllers/notes_controller.rb @@ -6,10 +6,15 @@ class NotesController < ProjectResourceController respond_to :js def index - notes + @notes = Notes::LoadContext.new(project, current_user, params).execute + if params[:target_type] == "merge_request" - @mixed_targets = true + @mixed_targets = true @main_target_type = params[:target_type].camelize + @discussions = discussions_from_notes + @has_diff = true + elsif params[:target_type] == "commit" + @has_diff = true end respond_with(@notes) @@ -40,7 +45,33 @@ class NotesController < ProjectResourceController protected - def notes - @notes = Notes::LoadContext.new(project, current_user, params).execute + def discussion_notes_for(note) + @notes.select do |other_note| + note.discussion_id == other_note.discussion_id + end + end + + def discussions_from_notes + discussion_ids = [] + discussions = [] + + @notes.each do |note| + next if discussion_ids.include?(note.discussion_id) + + # don't group notes for the main target + if for_main_target?(note) + discussions << [note] + else + discussions << discussion_notes_for(note) + discussion_ids << note.discussion_id + end + end + + discussions + end + + # Helps to distinguish e.g. commit notes in mr notes list + def for_main_target?(note) + !@mixed_targets || (@main_target_type == note.noteable_type && !note.for_diff_line?) end end -- cgit v1.2.1 From a048c955fda4de68a4e73e3fe2a4861e245926b8 Mon Sep 17 00:00:00 2001 From: Riyad Preukschas Date: Mon, 29 Oct 2012 18:24:25 +0100 Subject: Add JS behaviors --- app/assets/javascripts/behaviours/details_behavior.coffee | 5 +++++ app/assets/javascripts/behaviours/toggler_behaviour.coffee | 5 +++++ app/assets/stylesheets/behaviors.scss | 14 ++++++++++++++ app/assets/stylesheets/main.scss | 5 +++++ 4 files changed, 29 insertions(+) create mode 100644 app/assets/javascripts/behaviours/details_behavior.coffee create mode 100644 app/assets/javascripts/behaviours/toggler_behaviour.coffee create mode 100644 app/assets/stylesheets/behaviors.scss diff --git a/app/assets/javascripts/behaviours/details_behavior.coffee b/app/assets/javascripts/behaviours/details_behavior.coffee new file mode 100644 index 00000000000..f75284d9cf6 --- /dev/null +++ b/app/assets/javascripts/behaviours/details_behavior.coffee @@ -0,0 +1,5 @@ +$ -> + $("body").on "click", ".js-details-target", -> + container = $(@).closest ".js-details-container" + + container.toggleClass "open" diff --git a/app/assets/javascripts/behaviours/toggler_behaviour.coffee b/app/assets/javascripts/behaviours/toggler_behaviour.coffee new file mode 100644 index 00000000000..76f200d4667 --- /dev/null +++ b/app/assets/javascripts/behaviours/toggler_behaviour.coffee @@ -0,0 +1,5 @@ +$ -> + $("body").on "click", ".js-toggler-target", -> + container = $(@).closest ".js-toggler-container" + + container.toggleClass "on" diff --git a/app/assets/stylesheets/behaviors.scss b/app/assets/stylesheets/behaviors.scss new file mode 100644 index 00000000000..20854e7ee22 --- /dev/null +++ b/app/assets/stylesheets/behaviors.scss @@ -0,0 +1,14 @@ +// Details +//-------- +.js-details-container .content { display: none; } +.js-details-container .content.hide { display: block; } +.js-details-container.open .content { display: block; } +.js-details-container.open .content.hide { display: none; } + + +// Toggler +//-------- +.js-toggler-container .turn-on { display: inline-block; } +.js-toggler-container .turn-off { display: none; } +.js-toggler-container.on .turn-on { display: none; } +.js-toggler-container.on .turn-off { display: inline-block; } diff --git a/app/assets/stylesheets/main.scss b/app/assets/stylesheets/main.scss index bc7a74406ef..98d755219d9 100644 --- a/app/assets/stylesheets/main.scss +++ b/app/assets/stylesheets/main.scss @@ -83,6 +83,11 @@ $baseLineHeight: 18px !default; */ @import "common.scss"; +/** + * Styles necessary to support JS behaviours. + */ +@import "behaviors.scss"; + /** * Styles related to specific part of app */ -- cgit v1.2.1 From 7971383d53cdd30c6d2beddcb4d5289eb7b0c876 Mon Sep 17 00:00:00 2001 From: Riyad Preukschas Date: Mon, 29 Oct 2012 20:38:12 +0100 Subject: Rename the "Comments" tab for merge requests "Discussion" --- app/views/merge_requests/_show.html.haml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/views/merge_requests/_show.html.haml b/app/views/merge_requests/_show.html.haml index d12431da70b..a09a77c043e 100644 --- a/app/views/merge_requests/_show.html.haml +++ b/app/views/merge_requests/_show.html.haml @@ -7,9 +7,9 @@ - if @commits.present? %ul.nav.nav-tabs.mr_nav_tabs %li - = link_to "#notes", title: "Comments", "data-url" => project_merge_request_path(@project, @merge_request), class: "merge-notes-tab tab" do - %i.icon-comment - Comments + = link_to "#notes", title: "Discussion", "data-url" => project_merge_request_path(@project, @merge_request), class: "merge-notes-tab tab" do + %i.icon-comments + Discussion %li = link_to "#diffs", title: "Diff", "data-url" => diffs_project_merge_request_path(@project, @merge_request), class: "merge-diffs-tab tab" do %i.icon-list-alt -- cgit v1.2.1 From 0b3df2f12849a98c92e53d6d28a43b27c71608bd Mon Sep 17 00:00:00 2001 From: Riyad Preukschas Date: Mon, 29 Oct 2012 22:23:49 +0100 Subject: Add merge request note feature --- features/project/merge_requests.feature | 28 ++++- features/steps/project/project_merge_requests.rb | 143 +++++++++++++++++------ features/steps/shared/paths.rb | 5 + 3 files changed, 139 insertions(+), 37 deletions(-) diff --git a/features/project/merge_requests.feature b/features/project/merge_requests.feature index 80f00986466..5b8becbb6c9 100644 --- a/features/project/merge_requests.feature +++ b/features/project/merge_requests.feature @@ -35,8 +35,34 @@ Feature: Project Merge Requests Then I should see merge request "Wiki Feature" @javascript - Scenario: I comment merge request + Scenario: I comment on a merge request Given I visit merge request page "Bug NS-04" And I leave a comment like "XML attached" Then I should see comment "XML attached" + @javascript + Scenario: I comment on a merge request diff + Given project "Shop" have "Bug NS-05" open merge request with diffs inside + And I visit merge request page "Bug NS-05" + And I switch to the diff tab + And I leave a comment like "Line is wrong" on line 185 of the first file + And I switch to the merge request's comments tab + Then I should see a discussion has started on line 185 + + @javascript + Scenario: I comment on a line of a commit in merge request + Given project "Shop" have "Bug NS-05" open merge request with diffs inside + And I visit merge request page "Bug NS-05" + And I click on the first commit in the merge request + And I leave a comment like "Line is wrong" on line 185 of the first file + And I switch to the merge request's comments tab + Then I should see a discussion has started on commit bcf03b5de6c:L185 + + @javascript + Scenario: I comment on a commit in merge request + Given project "Shop" have "Bug NS-05" open merge request with diffs inside + And I visit merge request page "Bug NS-05" + And I click on the first commit in the merge request + And I leave a comment on the diff page + And I switch to the merge request's comments tab + Then I should see a discussion has started on commit bcf03b5de6c diff --git a/features/steps/project/project_merge_requests.rb b/features/steps/project/project_merge_requests.rb index d153ad28d2b..5248a5c469c 100644 --- a/features/steps/project/project_merge_requests.rb +++ b/features/steps/project/project_merge_requests.rb @@ -4,77 +4,148 @@ class ProjectMergeRequests < Spinach::FeatureSteps include SharedNote include SharedPaths - Then 'I should see "Bug NS-04" in merge requests' do - page.should have_content "Bug NS-04" + Given 'I click link "New Merge Request"' do + click_link "New Merge Request" end - And 'I should not see "Feature NS-03" in merge requests' do - page.should_not have_content "Feature NS-03" + Given 'I click link "Bug NS-04"' do + click_link "Bug NS-04" + end + + Given 'I click link "All"' do + click_link "All" end Given 'I click link "Closed"' do click_link "Closed" end - Then 'I should see "Feature NS-03" in merge requests' do - page.should have_content "Feature NS-03" + Then 'I should see merge request "Wiki Feature"' do + page.should have_content "Wiki Feature" end - And 'I should not see "Bug NS-04" in merge requests' do - page.should_not have_content "Bug NS-04" + Then 'I should see closed merge request "Bug NS-04"' do + mr = MergeRequest.find_by_title("Bug NS-04") + mr.closed.should be_true + page.should have_content "Closed by" end - Given 'I click link "All"' do - click_link "All" + Then 'I should see merge request "Bug NS-04"' do + page.should have_content "Bug NS-04" end - Given 'I click link "Bug NS-04"' do - click_link "Bug NS-04" + Then 'I should see "Bug NS-04" in merge requests' do + page.should have_content "Bug NS-04" end - Then 'I should see merge request "Bug NS-04"' do - page.should have_content "Bug NS-04" + Then 'I should see "Feature NS-03" in merge requests' do + page.should have_content "Feature NS-03" end - And 'I click link "Close"' do - click_link "Close" + And 'I should not see "Feature NS-03" in merge requests' do + page.should_not have_content "Feature NS-03" end - Then 'I should see closed merge request "Bug NS-04"' do - mr = MergeRequest.find_by_title("Bug NS-04") - mr.closed.should be_true - page.should have_content "Closed by" + + And 'I should not see "Bug NS-04" in merge requests' do + page.should_not have_content "Bug NS-04" end - Given 'I click link "New Merge Request"' do - click_link "New Merge Request" + And 'I click link "Close"' do + click_link "Close" end And 'I submit new merge request "Wiki Feature"' do - fill_in "merge_request_title", :with => "Wiki Feature" - select "master", :from => "merge_request_source_branch" - select "stable", :from => "merge_request_target_branch" + fill_in "merge_request_title", with: "Wiki Feature" + select "master", from: "merge_request_source_branch" + select "stable", from: "merge_request_target_branch" click_button "Save" end - Then 'I should see merge request "Wiki Feature"' do - page.should have_content "Wiki Feature" - end - And 'project "Shop" have "Bug NS-04" open merge request' do project = Project.find_by_name("Shop") create(:merge_request, - :title => "Bug NS-04", - :project => project, - :author => project.users.first) + title: "Bug NS-04", + project: project, + author: project.users.first) + end + + And 'project "Shop" have "Bug NS-05" open merge request with diffs inside' do + project = Project.find_by_name("Shop") + create(:merge_request_with_diffs, + title: "Bug NS-05", + project: project, + author: project.users.first) end And 'project "Shop" have "Feature NS-03" closed merge request' do project = Project.find_by_name("Shop") create(:merge_request, - :title => "Feature NS-03", - :project => project, - :author => project.users.first, - :closed => true) + title: "Feature NS-03", + project: project, + author: project.users.first, + closed: true) + end + + And 'I switch to the diff tab' do + mr = MergeRequest.find_by_title("Bug NS-05") + visit diffs_project_merge_request_path(mr.project, mr) + end + + And 'I switch to the merge request\'s comments tab' do + mr = MergeRequest.find_by_title("Bug NS-05") + visit project_merge_request_path(mr.project, mr) + end + + And 'I click on the first commit in the merge request' do + mr = MergeRequest.find_by_title("Bug NS-05") + click_link mr.commits.first.short_id(8) + end + + And 'I leave a comment on the diff page' do + within(:xpath, "//div[@class='note-form-holder']") do + fill_in "note_note", with: "One comment to rule them all" + click_button "Add Comment" + end + end + + And 'I leave a comment like "Line is wrong" on line 185 of the first file' do + within(:xpath, "//div[@class='diff_file'][1]") do + click_link "add-diff-line-note-0_185_185" + end + + within(:xpath, "//div[@class='line-note-form-holder']") do + fill_in "note_note", with: "Line is wrong" + click_button "Add Comment" + end + end + + Then 'I should see a discussion has started on line 185' do + mr = MergeRequest.find_by_title("Bug NS-05") + first_commit = mr.commits.first + first_diff = mr.diffs.first + page.should have_content "#{current_user.name} started a discussion on this merge request diff" + page.should have_content "#{first_diff.b_path}:L185" + page.should have_content "Line is wrong" + end + + Then 'I should see a discussion has started on commit bcf03b5de6c:L185' do + mr = MergeRequest.find_by_title("Bug NS-05") + first_commit = mr.commits.first + first_diff = mr.diffs.first + page.should have_content "#{current_user.name} started a discussion on commit" + page.should have_content first_commit.short_id(8) + page.should have_content "#{first_diff.b_path}:L185" + page.should have_content "Line is wrong" + end + + Then 'I should see a discussion has started on commit bcf03b5de6c' do + mr = MergeRequest.find_by_title("Bug NS-05") + first_commit = mr.st_commits.first + first_diff = mr.diffs.first + page.should have_content "#{current_user.name} started a discussion on commit" + page.should have_content first_commit.short_id(8) + page.should have_content "One comment to rule them all" + page.should_not have_content "#{first_diff.b_path}:L185" end end diff --git a/features/steps/shared/paths.rb b/features/steps/shared/paths.rb index a12576288df..bf20d5f8442 100644 --- a/features/steps/shared/paths.rb +++ b/features/steps/shared/paths.rb @@ -215,6 +215,11 @@ module SharedPaths visit project_merge_request_path(mr.project, mr) end + Given 'I visit merge request page "Bug NS-05"' do + mr = MergeRequest.find_by_title("Bug NS-05") + visit project_merge_request_path(mr.project, mr) + end + And 'I visit project "Shop" merge requests page' do visit project_merge_requests_path(Project.find_by_name("Shop")) end -- cgit v1.2.1 From 5c2f6d7f050222d2601218a0bec1dadcee5fcfa0 Mon Sep 17 00:00:00 2001 From: Riyad Preukschas Date: Sun, 2 Dec 2012 20:53:50 +0100 Subject: Update notes views to support discussions --- app/assets/javascripts/notes.js | 13 +- app/assets/stylesheets/sections/notes.scss | 144 ++++++++++++++++++++++- app/controllers/notes_controller.rb | 12 +- app/helpers/notes_helper.rb | 7 +- app/models/note.rb | 2 +- app/views/merge_requests/diffs.html.haml | 5 - app/views/notes/_discussion.html.haml | 46 ++++++++ app/views/notes/_discussion_diff.html.haml | 24 ++++ app/views/notes/_note.html.haml | 36 +++--- app/views/notes/_notes.html.haml | 15 ++- app/views/notes/_per_line_form.html.haml | 10 +- app/views/notes/_per_line_note_link.html.haml | 6 +- app/views/notes/_per_line_reply_button.html.haml | 6 +- app/views/notes/index.js.haml | 4 + 14 files changed, 270 insertions(+), 60 deletions(-) create mode 100644 app/views/notes/_discussion.html.haml create mode 100644 app/views/notes/_discussion_diff.html.haml diff --git a/app/assets/javascripts/notes.js b/app/assets/javascripts/notes.js index b6f65b7aa5e..91215fdbcbe 100644 --- a/app/assets/javascripts/notes.js +++ b/app/assets/javascripts/notes.js @@ -20,7 +20,7 @@ var NoteList = { // get initial set of notes this.getContent(); - $("#notes-list, #new-notes-list").on("ajax:success", ".delete-note", function() { + $("#notes-list, #new-notes-list").on("ajax:success", ".js-note-delete", function() { $(this).closest('li').fadeOut(function() { $(this).remove(); NoteList.updateVotes(); @@ -275,16 +275,23 @@ var NoteList = { var PerLineNotes = { init: function() { + $(".per_line_form .hide-button").on("click", function(){ + $(this).closest(".per_line_form").hide(); + return false; + }); + /** * Called when clicking on the "add note" or "reply" button for a diff line. * * Shows the note form below the line. * Sets some hidden fields in the form. */ - $(".diff_file_content").on("click", ".line_note_link, .line_note_reply_link", function(e) { + $(".diff_file_content").on("click", ".js-note-add-to-diff-line", function(e) { var form = $(".per_line_form"); $(this).closest("tr").after(form); form.find("#note_line_code").val($(this).data("lineCode")); + form.find("#note_noteable_type").val($(this).data("noteableType")); + form.find("#note_noteable_id").val($(this).data("noteableId")); form.show(); e.preventDefault(); }); @@ -297,7 +304,7 @@ var PerLineNotes = { * Removes the actual note from view. * Removes the reply button if the last note for that line has been removed. */ - $(".diff_file_content").on("ajax:success", ".delete-note", function() { + $(".diff_file_content").on("ajax:success", ".js-note-delete", function() { var trNote = $(this).closest("tr"); trNote.fadeOut(function() { $(this).remove(); diff --git a/app/assets/stylesheets/sections/notes.scss b/app/assets/stylesheets/sections/notes.scss index 0c2a56d62f5..18c17433c03 100644 --- a/app/assets/stylesheets/sections/notes.scss +++ b/app/assets/stylesheets/sections/notes.scss @@ -1,6 +1,5 @@ /** * Notes - * */ #notes-list, #new-notes-list { @@ -8,6 +7,133 @@ list-style: none; margin: 0px; padding: 0px; + + .discussion-header, + .note-header { + @extend .cgray; + padding-top: 5px; + padding-bottom: 15px; + + .avatar { + float: left; + margin-right: 10px; + } + + .discussion-last-update, + .note-last-update { + font-style: italic; + } + .note-author { + color: $style_color; + font-weight: bold; + &:hover { + color: $primary_color; + } + } + } + + .discussion { + padding: 8px 0; + overflow: hidden; + display: block; + position:relative; + + .discussion-body { + margin-left: 50px; + + .diff_file, + .discussion-hidden, + .notes { + @extend .borders; + background-color: #F9F9F9; + } + .diff_file .note { + border-bottom: 0px; + padding: 0px; + } + .discussion-hidden .note { + @extend .cgray; + padding: 8px; + text-align: center; + } + .notes .note { + border-color: #ddd; + padding: 8px; + } + } + } + + .note { + padding: 8px 0; + overflow: hidden; + display: block; + position:relative; + p { color: $style_color; } + + .avatar { + margin-top:3px; + } + .note-body { + margin-left:45px; + padding-top: 5px; + } + .note-header { + padding-bottom: 5px; + } + } +} + +#notes-list:not(.reversed) .note, +#notes-list:not(.reversed) .discussion, +#new-notes-list:not(.reversed) .note, +#new-notes-list:not(.reversed) .discussion { + border-bottom: 1px solid #eee; +} +#notes-list.reversed .note, +#notes-list.reversed .discussion, +#new-notes-list.reversed .note, +#new-notes-list.reversed .discussion { + border-top: 1px solid #eee; +} + + +/** + * Discussion/Note Actions + */ +.discussion, +.note { + &.note:hover { + .note-actions { display: block; } + } + .discussion-header:hover { + .discussion-actions { display: block; } + } + + .discussion-actions, + .note-actions { + display: none; + float: right; + + [class^="icon-"], + [class*="icon-"] { + font-size: 16px; + line-height: 16px; + vertical-align: middle; + } + + a { + @extend .cgray; + + &:hover { + color: $primary_color; + &.danger { @extend .cred; } + } + } + } +} +.diff_file .note .note-actions { + right: 0; + top: 0; } .issue_notes, @@ -18,13 +144,19 @@ } } -/* Note textare */ -#note_note { - height: 80px; - width: 99%; - font-size: 14px; +/* + * New Note Form + */ +.new_note { + /* Note textare */ + #note_note { + height:80px; + width:99%; + font-size:14px; + } } + #new_note { .attach_holder { display: none; diff --git a/app/controllers/notes_controller.rb b/app/controllers/notes_controller.rb index 79e8bcc7866..ca22af0de83 100644 --- a/app/controllers/notes_controller.rb +++ b/app/controllers/notes_controller.rb @@ -6,13 +6,15 @@ class NotesController < ProjectResourceController respond_to :js def index + @target_note = Note.new(noteable_type: params[:target_type].camelize, + noteable_id: params[:target_id]) + @target = @target_note.noteable @notes = Notes::LoadContext.new(project, current_user, params).execute if params[:target_type] == "merge_request" - @mixed_targets = true - @main_target_type = params[:target_type].camelize - @discussions = discussions_from_notes - @has_diff = true + @has_diff = true + @mixed_targets = true + @discussions = discussions_from_notes elsif params[:target_type] == "commit" @has_diff = true end @@ -72,6 +74,6 @@ class NotesController < ProjectResourceController # Helps to distinguish e.g. commit notes in mr notes list def for_main_target?(note) - !@mixed_targets || (@main_target_type == note.noteable_type && !note.for_diff_line?) + !@mixed_targets || (@target.class.name == note.noteable_type && !note.for_diff_line?) end end diff --git a/app/helpers/notes_helper.rb b/app/helpers/notes_helper.rb index 5cada379c3c..11d3a2ecc6c 100644 --- a/app/helpers/notes_helper.rb +++ b/app/helpers/notes_helper.rb @@ -9,13 +9,18 @@ module NotesHelper # Helps to distinguish e.g. commit notes in mr notes list def note_for_main_target?(note) - !@mixed_targets || (@main_target_type == note.noteable_type && !note.for_diff_line?) + !@mixed_targets || (@target.class.name == note.noteable_type && !note.for_diff_line?) end def link_to_commit_diff_line_note(note) if note.for_commit_diff_line? link_to "#{note.diff_file_name}:L#{note.diff_new_line}", project_commit_path(@project, note.noteable, anchor: note.line_code) end + end + def link_to_merge_request_diff_line_note(note) + if note.for_merge_request_diff_line? + link_to "#{note.diff_file_name}:L#{note.diff_new_line}", diffs_project_merge_request_path(note.project, note.noteable_id, anchor: note.line_code) + end end end diff --git a/app/models/note.rb b/app/models/note.rb index 6708fbc3758..a7bde1c5d8c 100644 --- a/app/models/note.rb +++ b/app/models/note.rb @@ -79,7 +79,7 @@ class Note < ActiveRecord::Base end def discussion_id - @discussion_id ||= [noteable_type, noteable_id, line_code].join.underscore.to_sym + @discussion_id ||= [:discussion, noteable_type.underscore, noteable_id, line_code].join("-").to_sym end # Returns true if this is a downvote note, diff --git a/app/views/merge_requests/diffs.html.haml b/app/views/merge_requests/diffs.html.haml index a755491c42e..2a5b8b1441e 100644 --- a/app/views/merge_requests/diffs.html.haml +++ b/app/views/merge_requests/diffs.html.haml @@ -1,6 +1 @@ = render "show" - -:javascript - $(function(){ - PerLineNotes.init(); - }); diff --git a/app/views/notes/_discussion.html.haml b/app/views/notes/_discussion.html.haml new file mode 100644 index 00000000000..8c050216b82 --- /dev/null +++ b/app/views/notes/_discussion.html.haml @@ -0,0 +1,46 @@ +- note = discussion_notes.first +.discussion.js-details-container.js-toggler-container.open{ class: note.discussion_id } + .discussion-header + .discussion-actions + = link_to "javascript:;", class: "js-details-target turn-on js-toggler-target" do + %i.icon-eye-close + Hide discussion + = link_to "javascript:;", class: "js-details-target turn-off js-toggler-target" do + %i.icon-eye-open + Show discussion + = image_tag gravatar_icon(note.author.email), class: "avatar s32" + %div + = link_to note.author_name, project_team_member_path(@project, @project.team_member_by_id(note.author)), class: "note-author" + - if note.for_merge_request? + started a discussion on this merge request diff + = link_to_merge_request_diff_line_note(note) + - elsif note.for_commit? + started a discussion on commit + #{link_to note.noteable.short_id, project_commit_path(@project, note.noteable)} + = link_to_commit_diff_line_note(note) if note.for_diff_line? + - else + %cite.cgray started a discussion + %div + - if discussion_notes.size > 1 + - last_note = discussion_notes.last + last updated by + = link_to last_note.author_name, project_team_member_path(@project, @project.team_member_by_id(last_note.author)), class: "note-author" + %span.discussion-last-update + = time_ago_in_words(last_note.updated_at) + ago + .discussion-body + - if note.for_diff_line? + .diff_file.content + = render "notes/discussion_diff", discussion_notes: discussion_notes, note: note + - else + .notes.content + = render discussion_notes + + -# will be shown when the other one is hidden + .discussion-hidden.content.hide + .note + %em Hidden discussion. + = link_to "javascript:;", class: "js-details-target js-toggler-target" do + %i.icon-eye-open + Show + diff --git a/app/views/notes/_discussion_diff.html.haml b/app/views/notes/_discussion_diff.html.haml new file mode 100644 index 00000000000..4cd227d68c6 --- /dev/null +++ b/app/views/notes/_discussion_diff.html.haml @@ -0,0 +1,24 @@ +- diff = note.diff +.diff_file_header + %i.icon-file + - if diff.deleted_file + %span{id: "#{diff.a_path}"}= diff.a_path + - else + %span{id: "#{diff.b_path}"}= diff.b_path + %br/ +.diff_file_content + %table + - each_diff_line(diff.diff.lines.to_a, note.diff_file_index) do |line, type, line_code, line_new, line_old| + %tr.line_holder{ id: line_code } + - if type == "match" + %td.old_line= "..." + %td.new_line= "..." + %td.line_content.matched= line + - else + %td.old_line= raw(type == "new" ? " " : line_old) + %td.new_line= raw(type == "old" ? " " : line_new) + %td.line_content{class: "noteable_line #{type} #{line_code}", "line_code" => line_code}= raw "#{line}  " + + - if line_code == note.line_code + = render "notes/per_line_notes_with_reply", notes: discussion_notes + - break # cut off diff after notes diff --git a/app/views/notes/_note.html.haml b/app/views/notes/_note.html.haml index 70baa212d10..cf88d2912e0 100644 --- a/app/views/notes/_note.html.haml +++ b/app/views/notes/_note.html.haml @@ -1,17 +1,18 @@ -%li{id: dom_id(note), class: "note"} - = image_tag gravatar_icon(note.author.email), class: "avatar s32" - %div.note-author - %strong= note.author_name - = link_to "##{dom_id(note)}", name: dom_id(note) do - %cite.cgray - = time_ago_in_words(note.updated_at) - ago - - - unless note_for_main_target?(note) - - if note.for_commit? - %span.cgray - on #{link_to note.noteable.short_id, project_commit_path(@project, note.noteable)} - = link_to_commit_diff_line_note(note) if note.for_diff_line? +%li{ id: dom_id(note), class: dom_class(note), data: { discussion: note.discussion_id } } + .note-header + .note-actions + = link_to "##{dom_id(note)}", name: dom_id(note) do + %i.icon-link + Link here +   + - if(note.author_id == current_user.id) || can?(current_user, :admin_note, @project) + = link_to project_note_path(@project, note), method: :delete, confirm: 'Are you sure?', remote: true, class: "danger js-note-delete" do + %i.icon-remove-circle + = image_tag gravatar_icon(note.author.email), class: "avatar s32" + = link_to note.author_name, project_team_member_path(@project, @project.team_member_by_id(note.author)), class: "note-author" + %span.note-last-update + = time_ago_in_words(note.updated_at) + ago -# only show vote if it's a note for the main target - if note_for_main_target?(note) @@ -24,13 +25,8 @@ %i.icon-thumbs-down \-1 - -# remove button - - if(note.author_id == current_user.id) || can?(current_user, :admin_note, @project) - = link_to [@project, note], confirm: 'Are you sure?', method: :delete, remote: true, class: "cred delete-note btn very_small" do - %i.icon-trash - Remove - %div.note-title + .note-body = preserve do = markdown(note.note) - if note.attachment.url diff --git a/app/views/notes/_notes.html.haml b/app/views/notes/_notes.html.haml index adb5dfcbf18..4904249aeff 100644 --- a/app/views/notes/_notes.html.haml +++ b/app/views/notes/_notes.html.haml @@ -1,4 +1,11 @@ -- @notes.each do |note| - - next unless note.author - = render "note", note: note - +- if @discussions.present? + - @discussions.each do |discussion_notes| + - note = discussion_notes.first + - if note_for_main_target?(note) + = render discussion_notes + - else + = render 'discussion', discussion_notes: discussion_notes +- else + - @notes.each do |note| + - next unless note.author + = render 'note', note: note diff --git a/app/views/notes/_per_line_form.html.haml b/app/views/notes/_per_line_form.html.haml index 460d49522bf..9210be977f6 100644 --- a/app/views/notes/_per_line_form.html.haml +++ b/app/views/notes/_per_line_form.html.haml @@ -17,7 +17,7 @@ .note_actions .buttons = f.submit 'Add Comment', class: "btn save-btn submit_note submit_inline_note", id: "submit_note" - = link_to "Cancel", "#", class: "btn hide-button" + = link_to "Cancel", "javascript:;", class: "btn hide-button" .options %h6.left Notify via email: .labels @@ -29,11 +29,3 @@ = label_tag :notify_author do = check_box_tag :notify_author, 1 , @note.noteable_type == "Commit" %span Commit author - -:javascript - $(function(){ - $(".per_line_form .hide-button").bind("click", function(){ - $('.per_line_form').hide(); - return false; - }); - }); diff --git a/app/views/notes/_per_line_note_link.html.haml b/app/views/notes/_per_line_note_link.html.haml index 16db3d809cb..d25577eac5a 100644 --- a/app/views/notes/_per_line_note_link.html.haml +++ b/app/views/notes/_per_line_note_link.html.haml @@ -1,6 +1,6 @@ = link_to "", "#", - id: "line-note-#{line_code}", - class: "line_note_link", + id: "add-diff-line-note-#{line_code}", + class: "line_note_link js-note-add-to-diff-line", data: @comments_target.merge({ line_code: line_code }), - title: "Add comment on line #{line_code[/[0-9]+$/]}" + title: "Add a comment to this line" diff --git a/app/views/notes/_per_line_reply_button.html.haml b/app/views/notes/_per_line_reply_button.html.haml index c9d2696675e..edd84eaef2d 100644 --- a/app/views/notes/_per_line_reply_button.html.haml +++ b/app/views/notes/_per_line_reply_button.html.haml @@ -1,10 +1,10 @@ %tr.line_notes_row.reply %td{colspan: 3} - = link_to "#", - class: "line_note_reply_link", + = link_to "javascript:;", + class: "line_note_reply_link js-note-add-to-diff-line", data: { line_code: note.line_code, noteable_type: note.noteable_type, noteable_id: note.noteable_id }, - title: "Add note for this line" do + title: "Add a comment to this line" do %i.icon-comment Reply diff --git a/app/views/notes/index.js.haml b/app/views/notes/index.js.haml index 3814dbd46a2..99da619c649 100644 --- a/app/views/notes/index.js.haml +++ b/app/views/notes/index.js.haml @@ -15,3 +15,7 @@ - if loading_more_notes? :plain NoteList.finishedLoadingMore(); + +- if @has_diff + :plain + PerLineNotes.init(); -- cgit v1.2.1 From 6c6f415cae54be4dae4522e901ed55c9dae04a15 Mon Sep 17 00:00:00 2001 From: Riyad Preukschas Date: Mon, 29 Oct 2012 19:37:37 +0100 Subject: Fix appending diff line notes --- app/contexts/notes/create_context.rb | 4 ++-- app/views/notes/_create_per_line_note.js.haml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/contexts/notes/create_context.rb b/app/contexts/notes/create_context.rb index d93adb835ef..1367dff4699 100644 --- a/app/contexts/notes/create_context.rb +++ b/app/contexts/notes/create_context.rb @@ -3,8 +3,8 @@ module Notes def execute note = project.notes.new(params[:note]) note.author = current_user - note.notify = true if params[:notify] == '1' - note.notify_author = true if params[:notify_author] == '1' + note.notify = params[:notify].present? + note.notify_author = params[:notify_author].present? note.save note end diff --git a/app/views/notes/_create_per_line_note.js.haml b/app/views/notes/_create_per_line_note.js.haml index eea9eb38be4..6f74699996b 100644 --- a/app/views/notes/_create_per_line_note.js.haml +++ b/app/views/notes/_create_per_line_note.js.haml @@ -6,7 +6,7 @@ // find the reply button for this line // (might not be there if this is the first note) - var trRpl = $("a.line_note_reply_link[data-line-code='#{note.line_code}']").closest("tr"); + var trRpl = $("a.line_note_reply_link[data-noteable-type='#{note.noteable_type}'][data-noteable-id='#{note.noteable_id}'][data-line-code='#{note.line_code}']").closest("tr"); if (trRpl.size() == 0) { // find the commented line ... var trEl = $(".#{note.line_code}").parent(); -- cgit v1.2.1 From ae067ee322e6702fb5ef0fd4f0cc4d4d5106cbde Mon Sep 17 00:00:00 2001 From: Riyad Preukschas Date: Tue, 30 Oct 2012 03:27:36 +0100 Subject: Fix vote counting --- app/helpers/notes_helper.rb | 16 +++--- app/models/note.rb | 16 +++++- app/roles/votes.rb | 21 ++++---- app/views/notes/_note.html.haml | 18 +++---- spec/factories.rb | 26 +++++++++ spec/models/note_spec.rb | 86 ++++++++++++++++++----------- spec/roles/votes_spec.rb | 116 +++++++++++++++++++++------------------- 7 files changed, 184 insertions(+), 115 deletions(-) diff --git a/app/helpers/notes_helper.rb b/app/helpers/notes_helper.rb index 11d3a2ecc6c..02dec2a043e 100644 --- a/app/helpers/notes_helper.rb +++ b/app/helpers/notes_helper.rb @@ -1,12 +1,4 @@ module NotesHelper - def loading_more_notes? - params[:loading_more].present? - end - - def loading_new_notes? - params[:loading_new].present? - end - # Helps to distinguish e.g. commit notes in mr notes list def note_for_main_target?(note) !@mixed_targets || (@target.class.name == note.noteable_type && !note.for_diff_line?) @@ -23,4 +15,12 @@ module NotesHelper link_to "#{note.diff_file_name}:L#{note.diff_new_line}", diffs_project_merge_request_path(note.project, note.noteable_id, anchor: note.line_code) end end + + def loading_more_notes? + params[:loading_more].present? + end + + def loading_new_notes? + params[:loading_new].present? + end end diff --git a/app/models/note.rb b/app/models/note.rb index a7bde1c5d8c..17b76615fa2 100644 --- a/app/models/note.rb +++ b/app/models/note.rb @@ -85,7 +85,9 @@ class Note < ActiveRecord::Base # Returns true if this is a downvote note, # otherwise false is returned def downvote? - note.start_with?('-1') || note.start_with?(':-1:') + votable? && (note.start_with?('-1') || + note.start_with?(':-1:') + ) end def for_commit? @@ -100,6 +102,10 @@ class Note < ActiveRecord::Base line_code.present? end + def for_issue? + noteable_type == "Issue" + end + def for_merge_request? noteable_type == "MergeRequest" end @@ -150,6 +156,12 @@ class Note < ActiveRecord::Base # Returns true if this is an upvote note, # otherwise false is returned def upvote? - note.start_with?('+1') || note.start_with?(':+1:') + votable? && (note.start_with?('+1') || + note.start_with?(':+1:') + ) + end + + def votable? + for_issue? || (for_merge_request? && !for_diff_line?) end end diff --git a/app/roles/votes.rb b/app/roles/votes.rb index 043a6feb777..10fa120c6e9 100644 --- a/app/roles/votes.rb +++ b/app/roles/votes.rb @@ -1,27 +1,28 @@ module Votes - # Return the number of +1 comments (upvotes) - def upvotes - notes.select(&:upvote?).size + + # Return the number of -1 comments (downvotes) + def downvotes + notes.select(&:downvote?).size end - def upvotes_in_percent + def downvotes_in_percent if votes_count.zero? 0 else - 100.0 / votes_count * upvotes + 100.0 - upvotes_in_percent end end - # Return the number of -1 comments (downvotes) - def downvotes - notes.select(&:downvote?).size + # Return the number of +1 comments (upvotes) + def upvotes + notes.select(&:upvote?).size end - def downvotes_in_percent + def upvotes_in_percent if votes_count.zero? 0 else - 100.0 - upvotes_in_percent + 100.0 / votes_count * upvotes end end diff --git a/app/views/notes/_note.html.haml b/app/views/notes/_note.html.haml index cf88d2912e0..c0c0b725146 100644 --- a/app/views/notes/_note.html.haml +++ b/app/views/notes/_note.html.haml @@ -14,16 +14,14 @@ = time_ago_in_words(note.updated_at) ago - -# only show vote if it's a note for the main target - - if note_for_main_target?(note) - - if note.upvote? - %span.vote.upvote.label.label-success - %i.icon-thumbs-up - \+1 - - if note.downvote? - %span.vote.downvote.label.label-error - %i.icon-thumbs-down - \-1 + - if note.upvote? + %span.vote.upvote.label.label-success + %i.icon-thumbs-up + \+1 + - if note.downvote? + %span.vote.downvote.label.label-error + %i.icon-thumbs-down + \-1 .note-body diff --git a/spec/factories.rb b/spec/factories.rb index a26a77dd860..ac49f14c563 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -91,6 +91,32 @@ FactoryGirl.define do factory :note do project note "Note" + author + + factory :note_on_commit, traits: [:on_commit] + factory :note_on_commit_line, traits: [:on_commit, :on_line] + factory :note_on_issue, traits: [:on_issue], aliases: [:votable_note] + factory :note_on_merge_request, traits: [:on_merge_request] + factory :note_on_merge_request_line, traits: [:on_merge_request, :on_line] + + trait :on_commit do + noteable_id "bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a" + noteable_type "Commit" + end + + trait :on_line do + line_code "0_184_184" + end + + trait :on_merge_request do + noteable_id 1 + noteable_type "MergeRequest" + end + + trait :on_issue do + noteable_id 1 + noteable_type "Issue" + end end factory :event do diff --git a/spec/models/note_spec.rb b/spec/models/note_spec.rb index 4f9352b9a14..4c1afd8a3b4 100644 --- a/spec/models/note_spec.rb +++ b/spec/models/note_spec.rb @@ -43,79 +43,105 @@ describe Note do let(:project) { create(:project) } it "recognizes a neutral note" do - note = create(:note, note: "This is not a +1 note") + note = create(:votable_note, note: "This is not a +1 note") note.should_not be_upvote note.should_not be_downvote end it "recognizes a neutral emoji note" do - note = build(:note, note: "I would :+1: this, but I don't want to") + note = build(:votable_note, note: "I would :+1: this, but I don't want to") note.should_not be_upvote note.should_not be_downvote end it "recognizes a +1 note" do - note = create(:note, note: "+1 for this") + note = create(:votable_note, note: "+1 for this") note.should be_upvote end it "recognizes a +1 emoji as a vote" do - note = build(:note, note: ":+1: for this") + note = build(:votable_note, note: ":+1: for this") note.should be_upvote end it "recognizes a -1 note" do - note = create(:note, note: "-1 for this") + note = create(:votable_note, note: "-1 for this") note.should be_downvote end it "recognizes a -1 emoji as a vote" do - note = build(:note, note: ":-1: for this") + note = build(:votable_note, note: ":-1: for this") note.should be_downvote end end - let(:project) { create(:project) } - let(:commit) { project.commit } - describe "Commit notes" do - before do - @note = create(:note, - noteable_id: commit.id, - noteable_type: "Commit") - end + let!(:note) { create(:note_on_commit, note: "+1 from me") } + let!(:commit) { note.noteable } it "should be accessible through #noteable" do - @note.noteable_id.should == commit.id - @note.noteable.should be_a(Commit) - @note.noteable.should == commit + note.noteable_id.should == commit.id + note.noteable.should be_a(Commit) + note.noteable.should == commit end it "should save a valid note" do - @note.noteable_id.should == commit.id - @note.noteable == commit + note.noteable_id.should == commit.id + note.noteable == commit end it "should be recognized by #for_commit?" do - @note.should be_for_commit + note.should be_for_commit end - end - describe "Pre-line commit notes" do - before do - @note = create(:note, - noteable_id: commit.id, - noteable_type: "Commit", - line_code: "0_16_1") + it "should not be votable" do + note.should_not be_votable end + end + + describe "Commit diff line notes" do + let!(:note) { create(:note_on_commit_line, note: "+1 from me") } + let!(:commit) { note.noteable } it "should save a valid note" do - @note.noteable_id.should == commit.id - @note.noteable.id.should == commit.id + note.noteable_id.should == commit.id + note.noteable.id.should == commit.id end it "should be recognized by #for_diff_line?" do - @note.should be_for_diff_line + note.should be_for_diff_line + end + + it "should be recognized by #for_commit_diff_line?" do + note.should be_for_commit_diff_line + end + + it "should not be votable" do + note.should_not be_votable + end + end + + describe "Issue notes" do + let!(:note) { create(:note_on_issue, note: "+1 from me") } + + it "should not be votable" do + note.should be_votable + end + end + + describe "Merge request notes" do + let!(:note) { create(:note_on_merge_request, note: "+1 from me") } + + it "should not be votable" do + note.should be_votable + end + end + + describe "Merge request diff line notes" do + let!(:note) { create(:note_on_merge_request_line, note: "+1 from me") } + + it "should not be votable" do + note.should_not be_votable end end diff --git a/spec/roles/votes_spec.rb b/spec/roles/votes_spec.rb index 98666022a8f..7e49ac781c2 100644 --- a/spec/roles/votes_spec.rb +++ b/spec/roles/votes_spec.rb @@ -1,132 +1,138 @@ require 'spec_helper' describe Issue do - let(:issue) { create(:issue) } + it { should include_module(Votes) } +end + +describe MergeRequest do + let(:merge_request) { FactoryGirl.create(:merge_request_with_diffs) } + + it { should include_module(Votes) } describe "#upvotes" do it "with no notes has a 0/0 score" do - issue.upvotes.should == 0 + merge_request.upvotes.should == 0 end it "should recognize non-+1 notes" do - issue.notes << create(:note, note: "No +1 here") - issue.should have(1).note - issue.notes.first.upvote?.should be_false - issue.upvotes.should == 0 + merge_request.notes << create(:note, note: "No +1 here") + merge_request.should have(1).note + merge_request.notes.first.upvote?.should be_false + merge_request.upvotes.should == 0 end it "should recognize a single +1 note" do - issue.notes << create(:note, note: "+1 This is awesome") - issue.upvotes.should == 1 + merge_request.notes << create(:note, note: "+1 This is awesome") + merge_request.upvotes.should == 1 end it "should recognize multiple +1 notes" do - issue.notes << create(:note, note: "+1 This is awesome") - issue.notes << create(:note, note: "+1 I want this") - issue.upvotes.should == 2 + merge_request.notes << create(:note, note: "+1 This is awesome") + merge_request.notes << create(:note, note: "+1 I want this") + merge_request.upvotes.should == 2 end end describe "#downvotes" do it "with no notes has a 0/0 score" do - issue.downvotes.should == 0 + merge_request.downvotes.should == 0 end it "should recognize non--1 notes" do - issue.notes << create(:note, note: "Almost got a -1") - issue.should have(1).note - issue.notes.first.downvote?.should be_false - issue.downvotes.should == 0 + merge_request.notes << create(:note, note: "Almost got a -1") + merge_request.should have(1).note + merge_request.notes.first.downvote?.should be_false + merge_request.downvotes.should == 0 end it "should recognize a single -1 note" do - issue.notes << create(:note, note: "-1 This is bad") - issue.downvotes.should == 1 + merge_request.notes << create(:note, note: "-1 This is bad") + merge_request.downvotes.should == 1 end it "should recognize multiple -1 notes" do - issue.notes << create(:note, note: "-1 This is bad") - issue.notes << create(:note, note: "-1 Away with this") - issue.downvotes.should == 2 + merge_request.notes << create(:note, note: "-1 This is bad") + merge_request.notes << create(:note, note: "-1 Away with this") + merge_request.downvotes.should == 2 end end describe "#votes_count" do it "with no notes has a 0/0 score" do - issue.votes_count.should == 0 + merge_request.votes_count.should == 0 end it "should recognize non notes" do - issue.notes << create(:note, note: "No +1 here") - issue.should have(1).note - issue.votes_count.should == 0 + merge_request.notes << create(:note, note: "No +1 here") + merge_request.should have(1).note + merge_request.votes_count.should == 0 end it "should recognize a single +1 note" do - issue.notes << create(:note, note: "+1 This is awesome") - issue.votes_count.should == 1 + merge_request.notes << create(:note, note: "+1 This is awesome") + merge_request.votes_count.should == 1 end it "should recognize a single -1 note" do - issue.notes << create(:note, note: "-1 This is bad") - issue.votes_count.should == 1 + merge_request.notes << create(:note, note: "-1 This is bad") + merge_request.votes_count.should == 1 end it "should recognize multiple notes" do - issue.notes << create(:note, note: "+1 This is awesome") - issue.notes << create(:note, note: "-1 This is bad") - issue.notes << create(:note, note: "+1 I want this") - issue.votes_count.should == 3 + merge_request.notes << create(:note, note: "+1 This is awesome") + merge_request.notes << create(:note, note: "-1 This is bad") + merge_request.notes << create(:note, note: "+1 I want this") + merge_request.votes_count.should == 3 end end describe "#upvotes_in_percent" do it "with no notes has a 0% score" do - issue.upvotes_in_percent.should == 0 + merge_request.upvotes_in_percent.should == 0 end it "should count a single 1 note as 100%" do - issue.notes << create(:note, note: "+1 This is awesome") - issue.upvotes_in_percent.should == 100 + merge_request.notes << create(:note, note: "+1 This is awesome") + merge_request.upvotes_in_percent.should == 100 end it "should count multiple +1 notes as 100%" do - issue.notes << create(:note, note: "+1 This is awesome") - issue.notes << create(:note, note: "+1 I want this") - issue.upvotes_in_percent.should == 100 + merge_request.notes << create(:note, note: "+1 This is awesome") + merge_request.notes << create(:note, note: "+1 I want this") + merge_request.upvotes_in_percent.should == 100 end it "should count fractions for multiple +1 and -1 notes correctly" do - issue.notes << create(:note, note: "+1 This is awesome") - issue.notes << create(:note, note: "+1 I want this") - issue.notes << create(:note, note: "-1 This is bad") - issue.notes << create(:note, note: "+1 me too") - issue.upvotes_in_percent.should == 75 + merge_request.notes << create(:note, note: "+1 This is awesome") + merge_request.notes << create(:note, note: "+1 I want this") + merge_request.notes << create(:note, note: "-1 This is bad") + merge_request.notes << create(:note, note: "+1 me too") + merge_request.upvotes_in_percent.should == 75 end end describe "#downvotes_in_percent" do it "with no notes has a 0% score" do - issue.downvotes_in_percent.should == 0 + merge_request.downvotes_in_percent.should == 0 end it "should count a single -1 note as 100%" do - issue.notes << create(:note, note: "-1 This is bad") - issue.downvotes_in_percent.should == 100 + merge_request.notes << create(:note, note: "-1 This is bad") + merge_request.downvotes_in_percent.should == 100 end it "should count multiple -1 notes as 100%" do - issue.notes << create(:note, note: "-1 This is bad") - issue.notes << create(:note, note: "-1 Away with this") - issue.downvotes_in_percent.should == 100 + merge_request.notes << create(:note, note: "-1 This is bad") + merge_request.notes << create(:note, note: "-1 Away with this") + merge_request.downvotes_in_percent.should == 100 end it "should count fractions for multiple +1 and -1 notes correctly" do - issue.notes << create(:note, note: "+1 This is awesome") - issue.notes << create(:note, note: "+1 I want this") - issue.notes << create(:note, note: "-1 This is bad") - issue.notes << create(:note, note: "+1 me too") - issue.downvotes_in_percent.should == 25 + merge_request.notes << create(:note, note: "+1 This is awesome") + merge_request.notes << create(:note, note: "+1 I want this") + merge_request.notes << create(:note, note: "-1 This is bad") + merge_request.notes << create(:note, note: "+1 me too") + merge_request.downvotes_in_percent.should == 25 end end end -- cgit v1.2.1 From bd60a4ed40ca52fd23e027de8f30e2f094eb6e5c Mon Sep 17 00:00:00 2001 From: Riyad Preukschas Date: Tue, 30 Oct 2012 21:55:51 +0100 Subject: Make notes JS know which notes are new in a request --- app/assets/javascripts/extensions/array.js | 7 ++++++ app/assets/javascripts/notes.js | 39 +++++++++++++++--------------- app/views/notes/index.js.haml | 7 +++--- 3 files changed, 31 insertions(+), 22 deletions(-) create mode 100644 app/assets/javascripts/extensions/array.js diff --git a/app/assets/javascripts/extensions/array.js b/app/assets/javascripts/extensions/array.js new file mode 100644 index 00000000000..7fccc9c9d5f --- /dev/null +++ b/app/assets/javascripts/extensions/array.js @@ -0,0 +1,7 @@ +Array.prototype.first = function() { + return this[0]; +} + +Array.prototype.last = function() { + return this[this.length-1]; +} \ No newline at end of file diff --git a/app/assets/javascripts/notes.js b/app/assets/javascripts/notes.js index 91215fdbcbe..f6a27c7ec6a 100644 --- a/app/assets/javascripts/notes.js +++ b/app/assets/javascripts/notes.js @@ -89,12 +89,12 @@ var NoteList = { getContent: function() { $.ajax({ - type: "GET", - url: this.notes_path, - data: this.target_params, - complete: function(){ $('.notes-status').removeClass("loading")}, - beforeSend: function() { $('.notes-status').addClass("loading") }, - dataType: "script"}); + url: this.notes_path, + data: this.target_params, + complete: function(){ $('.notes-status').removeClass("loading")}, + beforeSend: function() { $('.notes-status').addClass("loading") }, + dataType: "script" + }); }, /** @@ -102,9 +102,9 @@ var NoteList = { * Replaces the content of #notes-list with the given html. */ setContent: - function(first_id, last_id, html) { - this.top_id = first_id; - this.bottom_id = last_id; + function(newNoteIds, html) { + this.top_id = newNoteIds.first(); + this.bottom_id = newNoteIds.last(); $("#notes-list").html(html); // init infinite scrolling @@ -151,12 +151,12 @@ var NoteList = { // only load more notes if there are no "new" notes $('.loading').show(); $.ajax({ - type: "GET", url: this.notes_path, data: this.target_params + "&loading_more=1&" + (this.reversed ? "before_id" : "after_id") + "=" + this.bottom_id, complete: function(){ $('.notes-status').removeClass("loading")}, beforeSend: function() { $('.notes-status').addClass("loading") }, - dataType: "script"}); + dataType: "script" + }); }, /** @@ -164,9 +164,10 @@ var NoteList = { * Append notes to #notes-list. */ appendMoreNotes: - function(id, html) { - if(id != this.bottom_id) { - this.bottom_id = id; + function(newNoteIds, html) { + var lastNewNoteId = newNoteIds.last(); + if(lastNewNoteId != this.bottom_id) { + this.bottom_id = lastNewNoteId; $("#notes-list").append(html); } }, @@ -212,10 +213,10 @@ var NoteList = { getNew: function() { $.ajax({ - type: "GET", - url: this.notes_path, - data: this.target_params + "&loading_new=1&after_id=" + (this.reversed ? this.top_id : this.bottom_id), - dataType: "script"}); + url: this.notes_path, + data: this.target_params + "&loading_new=1&after_id=" + (this.reversed ? this.top_id : this.bottom_id), + dataType: "script" + }); }, /** @@ -223,7 +224,7 @@ var NoteList = { * Replaces the content of #new-notes-list with the given html. */ replaceNewNotes: - function(html) { + function(newNoteIds, html) { $("#new-notes-list").html(html); this.updateVotes(); }, diff --git a/app/views/notes/index.js.haml b/app/views/notes/index.js.haml index 99da619c649..cf46af6523b 100644 --- a/app/views/notes/index.js.haml +++ b/app/views/notes/index.js.haml @@ -1,15 +1,16 @@ - unless @notes.blank? + - new_note_ids = @notes.map(&:id) - if loading_more_notes? :plain - NoteList.appendMoreNotes(#{@notes.last.id}, "#{escape_javascript(render 'notes/notes')}"); + NoteList.appendMoreNotes(#{new_note_ids}, "#{escape_javascript(render 'notes/notes')}"); - elsif loading_new_notes? :plain - NoteList.replaceNewNotes("#{escape_javascript(render 'notes/notes')}"); + NoteList.replaceNewNotes(#{new_note_ids}, "#{escape_javascript(render 'notes/notes')}"); - else :plain - NoteList.setContent(#{@notes.first.id}, #{@notes.last.id}, "#{escape_javascript(render 'notes/notes')}"); + NoteList.setContent(#{new_note_ids}, "#{escape_javascript(render 'notes/notes')}"); - else - if loading_more_notes? -- cgit v1.2.1 From 534bd5a268bc3409db1352198222275ff844316d Mon Sep 17 00:00:00 2001 From: Riyad Preukschas Date: Fri, 16 Nov 2012 23:25:07 +0100 Subject: Fix emoji generation and styling --- app/assets/stylesheets/common.scss | 6 ++++++ lib/gitlab/markdown.rb | 26 +++++++++++++------------- 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/app/assets/stylesheets/common.scss b/app/assets/stylesheets/common.scss index 738ec2bf1dc..44bfb619ead 100644 --- a/app/assets/stylesheets/common.scss +++ b/app/assets/stylesheets/common.scss @@ -692,3 +692,9 @@ h1.http_status_code { } } } + +img.emoji { + height: 20px; + vertical-align: middle; + width: 20px; +} diff --git a/lib/gitlab/markdown.rb b/lib/gitlab/markdown.rb index ee0ee05c3be..23f408c697c 100644 --- a/lib/gitlab/markdown.rb +++ b/lib/gitlab/markdown.rb @@ -25,18 +25,6 @@ module Gitlab # >> gfm(":trollface:") # => "\":trollface:\" module Markdown - REFERENCE_PATTERN = %r{ - (\W)? # Prefix (1) - ( # Reference (2) - @([\w\._]+) # User name (3) - |[#!$](\d+) # Issue/MR/Snippet ID (4) - |([\h]{6,40}) # Commit ID (5) - ) - (\W)? # Suffix (6) - }x.freeze - - EMOJI_PATTERN = %r{(:(\S+):)}.freeze - attr_reader :html_options # Public: Parse the provided text with GitLab-Flavored Markdown @@ -92,6 +80,16 @@ module Gitlab text end + REFERENCE_PATTERN = %r{ + (\W)? # Prefix (1) + ( # Reference (2) + @([\w\._]+) # User name (3) + |[#!$](\d+) # Issue/MR/Snippet ID (4) + |([\h]{6,40}) # Commit ID (5) + ) + (\W)? # Suffix (6) + }x.freeze + def parse_references(text) # parse reference links text.gsub!(REFERENCE_PATTERN) do |match| @@ -111,11 +109,13 @@ module Gitlab end end + EMOJI_PATTERN = %r{(:(\S+):)}.freeze + def parse_emoji(text) # parse emoji text.gsub!(EMOJI_PATTERN) do |match| if valid_emoji?($2) - image_tag("emoji/#{$2}.png", size: "20x20", class: 'emoji', title: $1, alt: $1) + image_tag("emoji/#{$2}.png", class: 'emoji', title: $1, alt: $1) else match end -- cgit v1.2.1 From 3bc507e5c5139c3e43558152675e222dd4b25927 Mon Sep 17 00:00:00 2001 From: Riyad Preukschas Date: Sat, 17 Nov 2012 20:24:12 +0100 Subject: Rename diff note partials --- app/views/commit/show.html.haml | 2 +- app/views/commits/_text_file.html.haml | 4 +-- app/views/merge_requests/_show.html.haml | 2 +- app/views/notes/_create_diff_note.js.haml | 19 +++++++++++++ app/views/notes/_create_per_line_note.js.haml | 19 ------------- app/views/notes/_diff_note.html.haml | 5 ++++ app/views/notes/_diff_note_form.html.haml | 31 ++++++++++++++++++++++ app/views/notes/_diff_note_link.html.haml | 6 +++++ app/views/notes/_diff_notes_reply_button.html.haml | 10 +++++++ app/views/notes/_diff_notes_with_reply.html.haml | 3 +++ app/views/notes/_discussion_diff.html.haml | 2 +- app/views/notes/_per_line_form.html.haml | 31 ---------------------- app/views/notes/_per_line_note.html.haml | 5 ---- app/views/notes/_per_line_note_link.html.haml | 6 ----- .../notes/_per_line_notes_with_reply.html.haml | 3 --- app/views/notes/_per_line_reply_button.html.haml | 10 ------- app/views/notes/create.js.haml | 2 +- 17 files changed, 80 insertions(+), 80 deletions(-) create mode 100644 app/views/notes/_create_diff_note.js.haml delete mode 100644 app/views/notes/_create_per_line_note.js.haml create mode 100644 app/views/notes/_diff_note.html.haml create mode 100644 app/views/notes/_diff_note_form.html.haml create mode 100644 app/views/notes/_diff_note_link.html.haml create mode 100644 app/views/notes/_diff_notes_reply_button.html.haml create mode 100644 app/views/notes/_diff_notes_with_reply.html.haml delete mode 100644 app/views/notes/_per_line_form.html.haml delete mode 100644 app/views/notes/_per_line_note.html.haml delete mode 100644 app/views/notes/_per_line_note_link.html.haml delete mode 100644 app/views/notes/_per_line_notes_with_reply.html.haml delete mode 100644 app/views/notes/_per_line_reply_button.html.haml diff --git a/app/views/commit/show.html.haml b/app/views/commit/show.html.haml index 432d55b19e3..1157ae7adce 100644 --- a/app/views/commit/show.html.haml +++ b/app/views/commit/show.html.haml @@ -1,7 +1,7 @@ = render "commits/commit_box" = render "commits/diffs", diffs: @commit.diffs = render "notes/notes_with_form", tid: @commit.id, tt: "commit" -= render "notes/per_line_form" += render "notes/diff_note_form" :javascript diff --git a/app/views/commits/_text_file.html.haml b/app/views/commits/_text_file.html.haml index 5e7886922b4..3d9014c3a3f 100644 --- a/app/views/commits/_text_file.html.haml +++ b/app/views/commits/_text_file.html.haml @@ -13,11 +13,11 @@ %td.old_line = link_to raw(type == "new" ? " " : line_old), "##{line_code}", id: line_code - if @comments_allowed - = render "notes/per_line_note_link", line_code: line_code + = render "notes/diff_note_link", line_code: line_code %td.new_line= link_to raw(type == "old" ? " " : line_new) , "##{line_code}", id: line_code %td.line_content{class: "noteable_line #{type} #{line_code}", "line_code" => line_code}= raw "#{line}  " - if @reply_allowed - comments = @line_notes.select { |n| n.line_code == line_code }.sort_by(&:created_at) - unless comments.empty? - = render "notes/per_line_notes_with_reply", notes: comments + = render "notes/diff_notes_with_reply", notes: comments diff --git a/app/views/merge_requests/_show.html.haml b/app/views/merge_requests/_show.html.haml index a09a77c043e..9c5f4af26c3 100644 --- a/app/views/merge_requests/_show.html.haml +++ b/app/views/merge_requests/_show.html.haml @@ -21,7 +21,7 @@ = render "merge_requests/show/diffs" if @diffs .status -= render "notes/per_line_form" += render "notes/diff_note_form" :javascript $(function(){ diff --git a/app/views/notes/_create_diff_note.js.haml b/app/views/notes/_create_diff_note.js.haml new file mode 100644 index 00000000000..453053bd728 --- /dev/null +++ b/app/views/notes/_create_diff_note.js.haml @@ -0,0 +1,19 @@ +- if note.valid? + :plain + // hide and reset the form + $(".per_line_form").hide(); + $('.line-note-form-holder textarea').val(""); + + // find the reply button for this line + // (might not be there if this is the first note) + var trRpl = $("a.line_note_reply_link[data-noteable-type='#{note.noteable_type}'][data-noteable-id='#{note.noteable_id}'][data-line-code='#{note.line_code}']").closest("tr"); + if (trRpl.size() == 0) { + // find the commented line ... + var trEl = $(".#{note.line_code}").parent(); + // ... and insert the note and the reply button after it + trEl.after("#{escape_javascript(render "notes/diff_notes_reply_button", note: note)}"); + trEl.after("#{escape_javascript(render "notes/diff_note", note: note)}"); + } else { + // instert new note before reply button + trRpl.before("#{escape_javascript(render "notes/diff_note", note: note)}"); + } diff --git a/app/views/notes/_create_per_line_note.js.haml b/app/views/notes/_create_per_line_note.js.haml deleted file mode 100644 index 6f74699996b..00000000000 --- a/app/views/notes/_create_per_line_note.js.haml +++ /dev/null @@ -1,19 +0,0 @@ -- if note.valid? - :plain - // hide and reset the form - $(".per_line_form").hide(); - $('.line-note-form-holder textarea').val(""); - - // find the reply button for this line - // (might not be there if this is the first note) - var trRpl = $("a.line_note_reply_link[data-noteable-type='#{note.noteable_type}'][data-noteable-id='#{note.noteable_id}'][data-line-code='#{note.line_code}']").closest("tr"); - if (trRpl.size() == 0) { - // find the commented line ... - var trEl = $(".#{note.line_code}").parent(); - // ... and insert the note and the reply button after it - trEl.after("#{escape_javascript(render "notes/per_line_reply_button", note: note)}"); - trEl.after("#{escape_javascript(render "notes/per_line_note", note: note)}"); - } else { - // instert new note before reply button - trRpl.before("#{escape_javascript(render "notes/per_line_note", note: note)}"); - } diff --git a/app/views/notes/_diff_note.html.haml b/app/views/notes/_diff_note.html.haml new file mode 100644 index 00000000000..28bcd6e0c94 --- /dev/null +++ b/app/views/notes/_diff_note.html.haml @@ -0,0 +1,5 @@ +%tr.line_notes_row + %td{colspan: 3} + %ul + = render "notes/note", note: note + diff --git a/app/views/notes/_diff_note_form.html.haml b/app/views/notes/_diff_note_form.html.haml new file mode 100644 index 00000000000..9210be977f6 --- /dev/null +++ b/app/views/notes/_diff_note_form.html.haml @@ -0,0 +1,31 @@ +%table{style: "display:none;"} + %tr.per_line_form + %td{colspan: 3 } + .line-note-form-holder + = form_for [@project, @note], remote: "true", multipart: true do |f| + %h3.page_title Leave a comment + %div.span10 + -if @note.errors.any? + .alert-message.block-message.error + - @note.errors.full_messages.each do |msg| + %div= msg + + = f.hidden_field :noteable_id + = f.hidden_field :noteable_type + = f.hidden_field :line_code + = f.text_area :note, size: 255, class: 'line-note-text js-gfm-input' + .note_actions + .buttons + = f.submit 'Add Comment', class: "btn save-btn submit_note submit_inline_note", id: "submit_note" + = link_to "Cancel", "javascript:;", class: "btn hide-button" + .options + %h6.left Notify via email: + .labels + = label_tag :notify do + = check_box_tag :notify, 1, @note.noteable_type != "Commit" + %span Project team + + - if @note.notify_only_author?(current_user) + = label_tag :notify_author do + = check_box_tag :notify_author, 1 , @note.noteable_type == "Commit" + %span Commit author diff --git a/app/views/notes/_diff_note_link.html.haml b/app/views/notes/_diff_note_link.html.haml new file mode 100644 index 00000000000..d25577eac5a --- /dev/null +++ b/app/views/notes/_diff_note_link.html.haml @@ -0,0 +1,6 @@ += link_to "", + "#", + id: "add-diff-line-note-#{line_code}", + class: "line_note_link js-note-add-to-diff-line", + data: @comments_target.merge({ line_code: line_code }), + title: "Add a comment to this line" diff --git a/app/views/notes/_diff_notes_reply_button.html.haml b/app/views/notes/_diff_notes_reply_button.html.haml new file mode 100644 index 00000000000..edd84eaef2d --- /dev/null +++ b/app/views/notes/_diff_notes_reply_button.html.haml @@ -0,0 +1,10 @@ +%tr.line_notes_row.reply + %td{colspan: 3} + = link_to "javascript:;", + class: "line_note_reply_link js-note-add-to-diff-line", + data: { line_code: note.line_code, + noteable_type: note.noteable_type, + noteable_id: note.noteable_id }, + title: "Add a comment to this line" do + %i.icon-comment + Reply diff --git a/app/views/notes/_diff_notes_with_reply.html.haml b/app/views/notes/_diff_notes_with_reply.html.haml new file mode 100644 index 00000000000..43f954d532f --- /dev/null +++ b/app/views/notes/_diff_notes_with_reply.html.haml @@ -0,0 +1,3 @@ +- notes.each do |note| + = render "notes/diff_note", note: note += render "notes/diff_notes_reply_button", note: notes.first diff --git a/app/views/notes/_discussion_diff.html.haml b/app/views/notes/_discussion_diff.html.haml index 4cd227d68c6..544435af6ba 100644 --- a/app/views/notes/_discussion_diff.html.haml +++ b/app/views/notes/_discussion_diff.html.haml @@ -20,5 +20,5 @@ %td.line_content{class: "noteable_line #{type} #{line_code}", "line_code" => line_code}= raw "#{line}  " - if line_code == note.line_code - = render "notes/per_line_notes_with_reply", notes: discussion_notes + = render "notes/diff_notes_with_reply", notes: discussion_notes - break # cut off diff after notes diff --git a/app/views/notes/_per_line_form.html.haml b/app/views/notes/_per_line_form.html.haml deleted file mode 100644 index 9210be977f6..00000000000 --- a/app/views/notes/_per_line_form.html.haml +++ /dev/null @@ -1,31 +0,0 @@ -%table{style: "display:none;"} - %tr.per_line_form - %td{colspan: 3 } - .line-note-form-holder - = form_for [@project, @note], remote: "true", multipart: true do |f| - %h3.page_title Leave a comment - %div.span10 - -if @note.errors.any? - .alert-message.block-message.error - - @note.errors.full_messages.each do |msg| - %div= msg - - = f.hidden_field :noteable_id - = f.hidden_field :noteable_type - = f.hidden_field :line_code - = f.text_area :note, size: 255, class: 'line-note-text js-gfm-input' - .note_actions - .buttons - = f.submit 'Add Comment', class: "btn save-btn submit_note submit_inline_note", id: "submit_note" - = link_to "Cancel", "javascript:;", class: "btn hide-button" - .options - %h6.left Notify via email: - .labels - = label_tag :notify do - = check_box_tag :notify, 1, @note.noteable_type != "Commit" - %span Project team - - - if @note.notify_only_author?(current_user) - = label_tag :notify_author do - = check_box_tag :notify_author, 1 , @note.noteable_type == "Commit" - %span Commit author diff --git a/app/views/notes/_per_line_note.html.haml b/app/views/notes/_per_line_note.html.haml deleted file mode 100644 index 28bcd6e0c94..00000000000 --- a/app/views/notes/_per_line_note.html.haml +++ /dev/null @@ -1,5 +0,0 @@ -%tr.line_notes_row - %td{colspan: 3} - %ul - = render "notes/note", note: note - diff --git a/app/views/notes/_per_line_note_link.html.haml b/app/views/notes/_per_line_note_link.html.haml deleted file mode 100644 index d25577eac5a..00000000000 --- a/app/views/notes/_per_line_note_link.html.haml +++ /dev/null @@ -1,6 +0,0 @@ -= link_to "", - "#", - id: "add-diff-line-note-#{line_code}", - class: "line_note_link js-note-add-to-diff-line", - data: @comments_target.merge({ line_code: line_code }), - title: "Add a comment to this line" diff --git a/app/views/notes/_per_line_notes_with_reply.html.haml b/app/views/notes/_per_line_notes_with_reply.html.haml deleted file mode 100644 index ebe0c5c6c47..00000000000 --- a/app/views/notes/_per_line_notes_with_reply.html.haml +++ /dev/null @@ -1,3 +0,0 @@ -- notes.each do |note| - = render "notes/per_line_note", note: note -= render "notes/per_line_reply_button", note: notes.first diff --git a/app/views/notes/_per_line_reply_button.html.haml b/app/views/notes/_per_line_reply_button.html.haml deleted file mode 100644 index edd84eaef2d..00000000000 --- a/app/views/notes/_per_line_reply_button.html.haml +++ /dev/null @@ -1,10 +0,0 @@ -%tr.line_notes_row.reply - %td{colspan: 3} - = link_to "javascript:;", - class: "line_note_reply_link js-note-add-to-diff-line", - data: { line_code: note.line_code, - noteable_type: note.noteable_type, - noteable_id: note.noteable_id }, - title: "Add a comment to this line" do - %i.icon-comment - Reply diff --git a/app/views/notes/create.js.haml b/app/views/notes/create.js.haml index 03866591c4f..9921312e6eb 100644 --- a/app/views/notes/create.js.haml +++ b/app/views/notes/create.js.haml @@ -1,5 +1,5 @@ - if @note.line_code - = render "create_per_line_note", note: @note + = render "create_diff_note", note: @note - else = render "create_common_note", note: @note -- cgit v1.2.1 From 6d5c29dc2b08531fd82550e2e9e814382f58bb78 Mon Sep 17 00:00:00 2001 From: Riyad Preukschas Date: Sat, 17 Nov 2012 20:34:52 +0100 Subject: Inline diff_notes_reply_button partial --- app/views/notes/_create_diff_note.js.haml | 3 +-- app/views/notes/_diff_notes_reply_button.html.haml | 10 ---------- app/views/notes/_diff_notes_with_reply.html.haml | 14 +++++++++++++- 3 files changed, 14 insertions(+), 13 deletions(-) delete mode 100644 app/views/notes/_diff_notes_reply_button.html.haml diff --git a/app/views/notes/_create_diff_note.js.haml b/app/views/notes/_create_diff_note.js.haml index 453053bd728..462229bfe5d 100644 --- a/app/views/notes/_create_diff_note.js.haml +++ b/app/views/notes/_create_diff_note.js.haml @@ -11,8 +11,7 @@ // find the commented line ... var trEl = $(".#{note.line_code}").parent(); // ... and insert the note and the reply button after it - trEl.after("#{escape_javascript(render "notes/diff_notes_reply_button", note: note)}"); - trEl.after("#{escape_javascript(render "notes/diff_note", note: note)}"); + trEl.after("#{escape_javascript(render "notes/diff_notes_with_reply", notes: [note])}"); } else { // instert new note before reply button trRpl.before("#{escape_javascript(render "notes/diff_note", note: note)}"); diff --git a/app/views/notes/_diff_notes_reply_button.html.haml b/app/views/notes/_diff_notes_reply_button.html.haml deleted file mode 100644 index edd84eaef2d..00000000000 --- a/app/views/notes/_diff_notes_reply_button.html.haml +++ /dev/null @@ -1,10 +0,0 @@ -%tr.line_notes_row.reply - %td{colspan: 3} - = link_to "javascript:;", - class: "line_note_reply_link js-note-add-to-diff-line", - data: { line_code: note.line_code, - noteable_type: note.noteable_type, - noteable_id: note.noteable_id }, - title: "Add a comment to this line" do - %i.icon-comment - Reply diff --git a/app/views/notes/_diff_notes_with_reply.html.haml b/app/views/notes/_diff_notes_with_reply.html.haml index 43f954d532f..7ae328b83ed 100644 --- a/app/views/notes/_diff_notes_with_reply.html.haml +++ b/app/views/notes/_diff_notes_with_reply.html.haml @@ -1,3 +1,15 @@ - notes.each do |note| = render "notes/diff_note", note: note -= render "notes/diff_notes_reply_button", note: notes.first + +-# reply button +- note = notes.first # example note +%tr.line_notes_row.reply + %td{colspan: 3} + = link_to "javascript:;", + class: "line_note_reply_link js-note-add-to-diff-line", + data: { line_code: note.line_code, + noteable_type: note.noteable_type, + noteable_id: note.noteable_id }, + title: "Add a comment to this line" do + %i.icon-comment + Reply -- cgit v1.2.1 From 4d2278e7c64548137e1cfb9e4e56f842f15c29cb Mon Sep 17 00:00:00 2001 From: Riyad Preukschas Date: Sat, 17 Nov 2012 22:45:00 +0100 Subject: Rename commits/text_file partial to text_diff --- app/views/commits/_diffs.html.haml | 4 ++-- app/views/commits/_text_diff.html.haml | 23 +++++++++++++++++++++++ app/views/commits/_text_file.html.haml | 23 ----------------------- 3 files changed, 25 insertions(+), 25 deletions(-) create mode 100644 app/views/commits/_text_diff.html.haml delete mode 100644 app/views/commits/_text_file.html.haml diff --git a/app/views/commits/_diffs.html.haml b/app/views/commits/_diffs.html.haml index e7733f0506b..7fe45aa25bc 100644 --- a/app/views/commits/_diffs.html.haml +++ b/app/views/commits/_diffs.html.haml @@ -38,10 +38,10 @@ %br/ .diff_file_content - -# Skipp all non non-supported blobs + -# Skip all non-supported blobs - next unless file.respond_to?('text?') - if file.text? - = render "commits/text_file", diff: diff, index: i + = render "commits/text_diff", diff: diff, index: i - elsif file.image? - old_file = (@commit.prev_commit.tree / diff.old_path) if !@commit.prev_commit.nil? - if diff.renamed_file || diff.new_file || diff.deleted_file diff --git a/app/views/commits/_text_diff.html.haml b/app/views/commits/_text_diff.html.haml new file mode 100644 index 00000000000..3d9014c3a3f --- /dev/null +++ b/app/views/commits/_text_diff.html.haml @@ -0,0 +1,23 @@ +- too_big = diff.diff.lines.count > 1000 +- if too_big + %a.supp_diff_link Diff suppressed. Click to show + +%table{class: "#{'hide' if too_big}"} + - each_diff_line(diff.diff.lines.to_a, index) do |line, type, line_code, line_new, line_old| + %tr.line_holder{ id: line_code } + - if type == "match" + %td.old_line= "..." + %td.new_line= "..." + %td.line_content.matched= line + - else + %td.old_line + = link_to raw(type == "new" ? " " : line_old), "##{line_code}", id: line_code + - if @comments_allowed + = render "notes/diff_note_link", line_code: line_code + %td.new_line= link_to raw(type == "old" ? " " : line_new) , "##{line_code}", id: line_code + %td.line_content{class: "noteable_line #{type} #{line_code}", "line_code" => line_code}= raw "#{line}  " + + - if @reply_allowed + - comments = @line_notes.select { |n| n.line_code == line_code }.sort_by(&:created_at) + - unless comments.empty? + = render "notes/diff_notes_with_reply", notes: comments diff --git a/app/views/commits/_text_file.html.haml b/app/views/commits/_text_file.html.haml deleted file mode 100644 index 3d9014c3a3f..00000000000 --- a/app/views/commits/_text_file.html.haml +++ /dev/null @@ -1,23 +0,0 @@ -- too_big = diff.diff.lines.count > 1000 -- if too_big - %a.supp_diff_link Diff suppressed. Click to show - -%table{class: "#{'hide' if too_big}"} - - each_diff_line(diff.diff.lines.to_a, index) do |line, type, line_code, line_new, line_old| - %tr.line_holder{ id: line_code } - - if type == "match" - %td.old_line= "..." - %td.new_line= "..." - %td.line_content.matched= line - - else - %td.old_line - = link_to raw(type == "new" ? " " : line_old), "##{line_code}", id: line_code - - if @comments_allowed - = render "notes/diff_note_link", line_code: line_code - %td.new_line= link_to raw(type == "old" ? " " : line_new) , "##{line_code}", id: line_code - %td.line_content{class: "noteable_line #{type} #{line_code}", "line_code" => line_code}= raw "#{line}  " - - - if @reply_allowed - - comments = @line_notes.select { |n| n.line_code == line_code }.sort_by(&:created_at) - - unless comments.empty? - = render "notes/diff_notes_with_reply", notes: comments -- cgit v1.2.1 From 39834ec6409163e3339ed23ccdc9682932f45c9e Mon Sep 17 00:00:00 2001 From: Riyad Preukschas Date: Sun, 18 Nov 2012 00:41:30 +0100 Subject: Move diff notes into the actual diff content column --- app/assets/stylesheets/sections/commits.scss | 25 ++++++-- app/assets/stylesheets/sections/notes.scss | 70 +++++++++------------- app/views/commits/_text_diff.html.haml | 8 +-- app/views/notes/_common_form.html.haml | 2 +- app/views/notes/_create_diff_note.js.haml | 2 +- app/views/notes/_diff_note.html.haml | 5 -- app/views/notes/_diff_notes_with_reply.html.haml | 21 ++++--- app/views/notes/_notes_with_form.html.haml | 4 +- .../notes/_reversed_notes_with_form.html.haml | 4 +- 9 files changed, 68 insertions(+), 73 deletions(-) delete mode 100644 app/views/notes/_diff_note.html.haml diff --git a/app/assets/stylesheets/sections/commits.scss b/app/assets/stylesheets/sections/commits.scss index bf405bfcd51..a58d19ea179 100644 --- a/app/assets/stylesheets/sections/commits.scss +++ b/app/assets/stylesheets/sections/commits.scss @@ -176,12 +176,14 @@ } } } - .old_line, .new_line { - margin: 0px; - padding: 0px; - border: none; - background: #EEE; - color: #666; + .new_line, + .old_line, + .notes_line { + margin:0px; + padding:0px; + border:none; + background:#EEE; + color:#666; padding: 0px 5px; border-right: 1px solid #ccc; text-align: right; @@ -191,6 +193,13 @@ moz-user-select: none; -khtml-user-select: none; user-select: none; + + &.notes_line { + border: 1px solid #ccc; + border-left: none; + text-align: center; + padding: 10px 0; + } a { float: left; width: 35px; @@ -218,6 +227,10 @@ background: #fafafa; } } + .notes_content { + border: 1px solid #ccc; + border-width: 1px 0; + } } /** COMMIT BLOCK **/ diff --git a/app/assets/stylesheets/sections/notes.scss b/app/assets/stylesheets/sections/notes.scss index 18c17433c03..e678c424f79 100644 --- a/app/assets/stylesheets/sections/notes.scss +++ b/app/assets/stylesheets/sections/notes.scss @@ -1,8 +1,7 @@ /** * Notes */ -#notes-list, -#new-notes-list { +ul.notes { display: block; list-style: none; margin: 0px; @@ -81,21 +80,36 @@ padding-bottom: 5px; } } -} -#notes-list:not(.reversed) .note, -#notes-list:not(.reversed) .discussion, -#new-notes-list:not(.reversed) .note, -#new-notes-list:not(.reversed) .discussion { - border-bottom: 1px solid #eee; + // paint top or bottom borders depending on notes direction + &:not(.reversed) .note, + &:not(.reversed) .discussion { + border-bottom: 1px solid #eee; + } + &.reversed .note, + &.reversed .discussion { + border-top: 1px solid #eee; + } } -#notes-list.reversed .note, -#notes-list.reversed .discussion, -#new-notes-list.reversed .note, -#new-notes-list.reversed .discussion { - border-top: 1px solid #eee; + +.comment-btn { + @extend .save-btn; } +.diff_file tr.notes_holder { + font-family: $sansFontFamily; + font-size: 13px; + line-height: 18px; + + td:last-child { + background-color: $white; + padding-top: 0; + } + + .comment-btn { + margin-top: 8px; + } +} /** * Discussion/Note Actions @@ -225,36 +239,6 @@ p.notify_controls span{ font-weight: 700; } -tr.line_notes_row { - border-bottom: 1px solid #DDD; - border-left: 7px solid #2A79A3; - - &.reply { - background: #eee; - border-left: 7px solid #2A79A3; - border-top: 1px solid #ddd; - td { - padding: 7px 10px; - } - a.line_note_reply_link { - border: 1px solid #eaeaea; - @include border-radius(4px); - padding: 3px 10px; - margin-left: 5px; - color: white; - background: #2A79A3; - border-color: #2A79A3; - } - } - ul { - margin: 0; - li { - padding: 0; - border: none; - } - } -} - .line_notes_row, .per_line_form { font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; } .per_line_form { diff --git a/app/views/commits/_text_diff.html.haml b/app/views/commits/_text_diff.html.haml index 3d9014c3a3f..f5784dea511 100644 --- a/app/views/commits/_text_diff.html.haml +++ b/app/views/commits/_text_diff.html.haml @@ -17,7 +17,7 @@ %td.new_line= link_to raw(type == "old" ? " " : line_new) , "##{line_code}", id: line_code %td.line_content{class: "noteable_line #{type} #{line_code}", "line_code" => line_code}= raw "#{line}  " - - if @reply_allowed - - comments = @line_notes.select { |n| n.line_code == line_code }.sort_by(&:created_at) - - unless comments.empty? - = render "notes/diff_notes_with_reply", notes: comments + - if @reply_allowed + - comments = @line_notes.select { |n| n.line_code == line_code }.sort_by(&:created_at) + - unless comments.empty? + = render "notes/diff_notes_with_reply", notes: comments diff --git a/app/views/notes/_common_form.html.haml b/app/views/notes/_common_form.html.haml index 0725082d504..a1e87c87d20 100644 --- a/app/views/notes/_common_form.html.haml +++ b/app/views/notes/_common_form.html.haml @@ -16,7 +16,7 @@ .row.note_advanced_opts .span3 - = f.submit 'Add Comment', class: "btn success submit_note grouped", id: "submit_note" + = f.submit 'Add Comment', class: "btn comment-btn submit_note grouped", id: "submit_note" = link_to 'Preview', preview_project_notes_path(@project), class: 'btn grouped', id: 'preview-link' .span4.notify_opts %h6.left Notify via email: diff --git a/app/views/notes/_create_diff_note.js.haml b/app/views/notes/_create_diff_note.js.haml index 462229bfe5d..a0c065ea4f7 100644 --- a/app/views/notes/_create_diff_note.js.haml +++ b/app/views/notes/_create_diff_note.js.haml @@ -6,7 +6,7 @@ // find the reply button for this line // (might not be there if this is the first note) - var trRpl = $("a.line_note_reply_link[data-noteable-type='#{note.noteable_type}'][data-noteable-id='#{note.noteable_id}'][data-line-code='#{note.line_code}']").closest("tr"); + var trRpl = $(".js-note-add-to-diff-line[data-noteable-type='#{note.noteable_type}'][data-noteable-id='#{note.noteable_id}'][data-line-code='#{note.line_code}']").closest("tr"); if (trRpl.size() == 0) { // find the commented line ... var trEl = $(".#{note.line_code}").parent(); diff --git a/app/views/notes/_diff_note.html.haml b/app/views/notes/_diff_note.html.haml deleted file mode 100644 index 28bcd6e0c94..00000000000 --- a/app/views/notes/_diff_note.html.haml +++ /dev/null @@ -1,5 +0,0 @@ -%tr.line_notes_row - %td{colspan: 3} - %ul - = render "notes/note", note: note - diff --git a/app/views/notes/_diff_notes_with_reply.html.haml b/app/views/notes/_diff_notes_with_reply.html.haml index 7ae328b83ed..e3e5b291393 100644 --- a/app/views/notes/_diff_notes_with_reply.html.haml +++ b/app/views/notes/_diff_notes_with_reply.html.haml @@ -1,15 +1,18 @@ -- notes.each do |note| - = render "notes/diff_note", note: note +%tr.notes_holder + %td.notes_line{ colspan: 2 } + %span.btn.disabled + %i.icon-comment + = notes.count + %td.notes_content + %ul.notes + = render notes --# reply button -- note = notes.first # example note -%tr.line_notes_row.reply - %td{colspan: 3} - = link_to "javascript:;", - class: "line_note_reply_link js-note-add-to-diff-line", + -# reply button + - note = notes.first # example note + %button{ class: "btn comment-btn js-note-add-to-diff-line", data: { line_code: note.line_code, noteable_type: note.noteable_type, noteable_id: note.noteable_id }, - title: "Add a comment to this line" do + title: "Add a comment to this line" } %i.icon-comment Reply diff --git a/app/views/notes/_notes_with_form.html.haml b/app/views/notes/_notes_with_form.html.haml index 53716c1d3f4..713f8aac668 100644 --- a/app/views/notes/_notes_with_form.html.haml +++ b/app/views/notes/_notes_with_form.html.haml @@ -1,5 +1,5 @@ -%ul#notes-list -%ul#new-notes-list +%ul#notes-list.notes +%ul#new-notes-list.notes .notes-status - if can? current_user, :write_note, @project diff --git a/app/views/notes/_reversed_notes_with_form.html.haml b/app/views/notes/_reversed_notes_with_form.html.haml index 24d599244b4..9c28d015c72 100644 --- a/app/views/notes/_reversed_notes_with_form.html.haml +++ b/app/views/notes/_reversed_notes_with_form.html.haml @@ -1,8 +1,8 @@ - if can? current_user, :write_note, @project = render "notes/common_form" -%ul.reversed#new-notes-list -%ul.reversed#notes-list +%ul#new-notes-list.reversed.notes +%ul#notes-list.reversed.notes .notes-status :javascript -- cgit v1.2.1 From 06ea1228404e56ee3356739a5e9a935f8d570b05 Mon Sep 17 00:00:00 2001 From: Riyad Preukschas Date: Tue, 20 Nov 2012 17:46:55 +0100 Subject: Refactor diff notes creation --- app/assets/javascripts/notes.js | 249 ++++++++++++++++------- app/assets/stylesheets/sections/commits.scss | 10 - app/assets/stylesheets/sections/notes.scss | 217 +++++++++----------- app/controllers/notes_controller.rb | 3 - app/views/commit/show.html.haml | 5 - app/views/merge_requests/_show.html.haml | 2 - app/views/merge_requests/diffs.js.haml | 4 - app/views/notes/_common_form.html.haml | 4 +- app/views/notes/_create_diff_note.js.haml | 18 +- app/views/notes/_diff_note_form.html.haml | 53 +++-- app/views/notes/_diff_note_link.html.haml | 11 +- app/views/notes/_diff_notes_with_reply.html.haml | 16 +- app/views/notes/_notes_with_form.html.haml | 4 +- app/views/notes/create.js.haml | 4 - app/views/notes/index.js.haml | 4 - 15 files changed, 321 insertions(+), 283 deletions(-) diff --git a/app/assets/javascripts/notes.js b/app/assets/javascripts/notes.js index f6a27c7ec6a..e5c233ef4fc 100644 --- a/app/assets/javascripts/notes.js +++ b/app/assets/javascripts/notes.js @@ -17,34 +17,6 @@ var NoteList = { this.reversed = $("#notes-list").is(".reversed"); this.target_params = "target_type=" + this.target_type + "&target_id=" + this.target_id; - // get initial set of notes - this.getContent(); - - $("#notes-list, #new-notes-list").on("ajax:success", ".js-note-delete", function() { - $(this).closest('li').fadeOut(function() { - $(this).remove(); - NoteList.updateVotes(); - }); - }); - - $(".note-form-holder").on("ajax:before", function(){ - $(".submit_note").disable(); - }) - - $(".note-form-holder").on("ajax:complete", function(){ - $(".submit_note").enable(); - $('#preview-note').hide(); - $('#note_note').show(); - }) - - disableButtonIfEmptyField(".note-text", ".submit_note"); - - $("#note_attachment").change(function(e){ - var val = $('.input-file').val(); - var filename = val.replace(/^.*[\\\/]/, ''); - $(".file_name").text(filename); - }); - if(this.reversed) { var textarea = $(".note-text"); $('.note_advanced_opts').hide(); @@ -55,6 +27,17 @@ var NoteList = { }); } + // get initial set of notes + this.getContent(); + + disableButtonIfEmptyField(".js-note-text", ".js-comment-button"); + + $("#note_attachment").change(function(e){ + var val = $('.input-file').val(); + var filename = val.replace(/^.*[\\\/]/, ''); + $(".file_name").text(filename); + }); + // Setup note preview $(document).on('click', '#preview-link', function(e) { $('#preview-note').text('Loading...'); @@ -72,11 +55,170 @@ var NoteList = { } $('#preview-note, #note_note').toggle(); - e.preventDefault(); + });+ + + $(document).on("click", + ".js-add-diff-note-button", + NoteList.addDiffNote); + + // reply to diff notes + $(document).on("click", + ".js-diff-note-reply-button", + NoteList.replyToDiffNote); + + // hide diff note form + $(document).on("click", + ".js-hide-diff-note-form", + NoteList.removeDiffNoteForm); + + // do some diff note specific housekeeping when removing a diff note + $(document).on("click", + ".diff_file .js-note-delete", + NoteList.removeDiffNote); + + // remove a note (in general) + $(document).on("click", + ".js-note-delete", + NoteList.removeNote); + + // clean up previews for forms + $(document).on("ajax:complete", ".note-form-holder", function(){ + $(this).find('#preview-note').hide(); + $(this).find('#note_note').show(); }); }, + /** + * Event handlers + */ + + + /** + * Called when clicking on the "add a comment" button on the side of a diff line. + * + * Inserts a temporary row for the form below the line. + * Sets up the form and shows it. + */ + addDiffNote: function(e) { + // find the form + var form = $(".js-note-forms .js-diff-note-form"); + var row = $(this).closest("tr"); + var nextRow = row.next(); + + // does it already have notes? + if (nextRow.is(".notes_holder")) { + $.proxy(NoteList.replyToDiffNote, + nextRow.find(".js-diff-note-reply-button") + ).call(); + } else { + // add a notes row and insert the form + row.after(''); + form.clone().appendTo(row.next().find(".notes_content")); + + // show the form + NoteList.setupDiffNoteForm($(this), row.next().find("form")); + } + + e.preventDefault(); + }, + + /** + * Called in response to deleting a note on a diff line. + * + * Removes the actual note from view. + * Removes the whole notes row if the last note for that line is being removed. + * + * Note: must be called before removeNote() + */ + removeDiffNote: function() { + var notes = $(this).closest(".notes"); + + // check if this is the last note for this line + if (notes.find(".note").length === 1) { + notes.closest("tr").remove(); + } + }, + + /** + * Called in response to "cancel" on a diff note form. + * + * Shows the reply button again. + * Removes the form and if necessary it's temporary row. + */ + removeDiffNoteForm: function(e) { + var form = $(this).closest("form"); + var row = form.closest("tr"); + + // show the reply button (will only work for replys) + form.prev(".js-diff-note-reply-button").show(); + + if (row.is(".js-temp-notes-holder")) { + // remove temporary row + row.remove(); + } else { + // only remove the form + form.remove(); + } + + e.preventDefault(); + }, + + /** + * Called in response to deleting a note of any kind. + * + * Removes the actual note from view. + */ + removeNote: function() { + $(this).closest(".note").remove(); + NoteList.updateVotes(); + }, + + /** + * Called when clicking on the "reply" button for a diff line. + * + * Shows the note form below the notes. + */ + replyToDiffNote: function() { + // find the form + var form = $(".js-note-forms .js-diff-note-form"); + + + // hide reply button + $(this).hide(); + // insert the form after the button + form.clone().insertAfter($(this)); + + // show the form + NoteList.setupDiffNoteForm($(this), $(this).next("form")); + }, + + /** + * Shows the diff line form and does some setup. + * + * Sets some hidden fields in the form. + * + * Note: "this" must have the "discussionId", "lineCode", "noteableType" and + * "noteableId" data attributes set. + */ + setupDiffNoteForm: function(data_holder, form) { + // setup note target + form.attr("rel", data_holder.data("discussionId")); + form.find("#note_line_code").val(data_holder.data("lineCode")); + form.find("#note_noteable_type").val(data_holder.data("noteableType")); + form.find("#note_noteable_id").val(data_holder.data("noteableId")); + + // setup interaction + disableButtonIfEmptyField(form.find(".js-note-text"), form.find(".js-comment-button")); + setupGfmAutoComplete(); + + // cleanup after successfully creating a diff note + form.on("ajax:success", NoteList.removeDiffNoteForm); + + form.show(); + }, + + /** * Handle loading the initial set of notes. * And set up loading more notes when scrolling to the bottom of the page. @@ -272,52 +414,3 @@ var NoteList = { } } }; - -var PerLineNotes = { - init: - function() { - $(".per_line_form .hide-button").on("click", function(){ - $(this).closest(".per_line_form").hide(); - return false; - }); - - /** - * Called when clicking on the "add note" or "reply" button for a diff line. - * - * Shows the note form below the line. - * Sets some hidden fields in the form. - */ - $(".diff_file_content").on("click", ".js-note-add-to-diff-line", function(e) { - var form = $(".per_line_form"); - $(this).closest("tr").after(form); - form.find("#note_line_code").val($(this).data("lineCode")); - form.find("#note_noteable_type").val($(this).data("noteableType")); - form.find("#note_noteable_id").val($(this).data("noteableId")); - form.show(); - e.preventDefault(); - }); - - disableButtonIfEmptyField(".line-note-text", ".submit_inline_note"); - - /** - * Called in response to successfully deleting a note on a diff line. - * - * Removes the actual note from view. - * Removes the reply button if the last note for that line has been removed. - */ - $(".diff_file_content").on("ajax:success", ".js-note-delete", function() { - var trNote = $(this).closest("tr"); - trNote.fadeOut(function() { - $(this).remove(); - }); - - // check if this is the last note for this line - // elements must really be removed for this to work reliably - var trLine = trNote.prev(); - var trRpl = trNote.next(); - if (trLine.is(".line_holder") && trRpl.is(".reply")) { - trRpl.fadeOut(function() { $(this).remove(); }); - } - }); - } -} diff --git a/app/assets/stylesheets/sections/commits.scss b/app/assets/stylesheets/sections/commits.scss index a58d19ea179..b96e460c4f3 100644 --- a/app/assets/stylesheets/sections/commits.scss +++ b/app/assets/stylesheets/sections/commits.scss @@ -194,12 +194,6 @@ -khtml-user-select: none; user-select: none; - &.notes_line { - border: 1px solid #ccc; - border-left: none; - text-align: center; - padding: 10px 0; - } a { float: left; width: 35px; @@ -227,10 +221,6 @@ background: #fafafa; } } - .notes_content { - border: 1px solid #ccc; - border-width: 1px 0; - } } /** COMMIT BLOCK **/ diff --git a/app/assets/stylesheets/sections/notes.scss b/app/assets/stylesheets/sections/notes.scss index e678c424f79..97739017c2c 100644 --- a/app/assets/stylesheets/sections/notes.scss +++ b/app/assets/stylesheets/sections/notes.scss @@ -92,23 +92,58 @@ ul.notes { } } -.comment-btn { - @extend .save-btn; -} - .diff_file tr.notes_holder { font-family: $sansFontFamily; font-size: 13px; line-height: 18px; - td:last-child { - background-color: $white; - padding-top: 0; + td { + border: 1px solid #ddd; + border-left: none; + + &.notes_line { + text-align: center; + padding: 10px 0; + } + &.notes_content { + background-color: $white; + border-width: 1px 0; + padding-top: 0; + } } .comment-btn { margin-top: 8px; } + + // TODO: start cleanup + form { + // hide it by default + display: none; + margin: 8px 0; + + .note_actions { + margin:0; + padding-top: 10px; + + .buttons { + float:left; + width:300px; + } + .options { + .labels { + float:left; + padding-left:10px; + label { + padding: 6px 0; + margin: 0; + width:120px; + } + } + } + } + } + // TODO: end cleanup } /** @@ -158,74 +193,6 @@ ul.notes { } } -/* - * New Note Form - */ -.new_note { - /* Note textare */ - #note_note { - height:80px; - width:99%; - font-size:14px; - } -} - - -#new_note { - .attach_holder { - display: none; - } -} - -.preview_note { - margin: 2px; - border: 1px solid #ddd; - padding: 10px; - min-height: 60px; - background: #f5f5f5; -} - -.note { - padding: 8px 0; - overflow: hidden; - display: block; - position: relative; - img {float: left; margin-right: 10px;} - img.emoji {float: none;margin: 0;} - .note-author cite{font-style: italic;} - p { color: $style_color; } - .note-author { color: $style_color;} - - .note-title { margin-left: 45px; padding-top: 5px;} - .avatar { - margin-top: 3px; - } - - .delete-note { - display: none; - position: absolute; - right: 0; - top: 0; - } - - &:hover { - .delete-note { display: block; } - } -} -#notes-list:not(.reversed) .note, -#new-notes-list:not(.reversed) .note { - border-bottom: 1px solid #eee; -} -#notes-list.reversed .note, -#new-notes-list.reversed .note { - border-top: 1px solid #eee; -} - -/* mark vote notes */ -.voting_notes .note { - padding: 8px 0; -} - .notes-status { margin: 18px; } @@ -239,62 +206,74 @@ p.notify_controls span{ font-weight: 700; } -.line_notes_row, .per_line_form { font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; } +/** + * add line note button on the side of diffs + */ +.diff_file tr.line_holder { + .add-diff-note { + position:absolute; + margin-left:-70px; + margin-top:-10px; + z-index:10; + background: url("comment_add.png") no-repeat left 0; + width:32px; + height:32px; + + opacity: 0.0; + filter: alpha(opacity=0); -.per_line_form { - background: #f5f5f5; - border-top: 1px solid #eee; - form { margin: 0; } - td { - border-bottom: 1px solid #ddd; + &:hover { + opacity: 1.0; + filter: alpha(opacity=100); + } } - .note_actions { - margin: 0; - padding-top: 10px; - .buttons { - float: left; - width: 300px; - } - .options { - .labels { - float: left; - padding-left: 10px; - label { - padding: 6px 0; - margin: 0; - width: 120px; - } - } + &:hover > td { + background: $hover !important; + + .add-diff-note { + opacity: 1.0; + filter: alpha(opacity=100); } } } -td .line_note_link { - position: absolute; - margin-left:-70px; - margin-top:-10px; - z-index: 10; - background: url("comment_add.png") no-repeat left 0; - width: 32px; - height: 32px; - - opacity: 0.0; - filter: alpha(opacity=0); - - &:hover { - opacity: 1.0; - filter: alpha(opacity=100); +/** + * Note Forms + */ + +.comment-btn { + @extend .save-btn; +} +.new_note { + textarea { + height:80px; + width:99%; + font-size:14px; + } +} +.note-forms { + .new_diff_note { + display: none; + } +} + + +#new_note { + .attach_holder { + display:none; } } -.diff_file_content tr.line_holder:hover > td { background: $hover !important; } -.diff_file_content tr.line_holder:hover > td .line_note_link { - opacity: 1.0; - filter: alpha(opacity=100); +.preview_note { + margin: 2px; + border: 1px solid #ddd; + padding: 10px; + min-height: 60px; + background:#f5f5f5; } -.new_note { +form.new_note { .input-file { font: 500px monospace; opacity: 0; diff --git a/app/controllers/notes_controller.rb b/app/controllers/notes_controller.rb index ca22af0de83..4f8b7bb9da3 100644 --- a/app/controllers/notes_controller.rb +++ b/app/controllers/notes_controller.rb @@ -12,11 +12,8 @@ class NotesController < ProjectResourceController @notes = Notes::LoadContext.new(project, current_user, params).execute if params[:target_type] == "merge_request" - @has_diff = true @mixed_targets = true @discussions = discussions_from_notes - elsif params[:target_type] == "commit" - @has_diff = true end respond_with(@notes) diff --git a/app/views/commit/show.html.haml b/app/views/commit/show.html.haml index 1157ae7adce..cef6b2f5bd5 100644 --- a/app/views/commit/show.html.haml +++ b/app/views/commit/show.html.haml @@ -1,12 +1,9 @@ = render "commits/commit_box" = render "commits/diffs", diffs: @commit.diffs = render "notes/notes_with_form", tid: @commit.id, tt: "commit" -= render "notes/diff_note_form" - :javascript $(function(){ - PerLineNotes.init(); var w, h; $('.diff_file').each(function(){ $('.image.diff_removed img', this).on('load', $.proxy(function(event){ @@ -19,7 +16,5 @@ , h = event.currentTarget.naturalHeight; $('.image.diff_added .image-info', this).append(' | W: ' + w + 'px | H: ' + h + 'px'); }, this)); - }); - }); diff --git a/app/views/merge_requests/_show.html.haml b/app/views/merge_requests/_show.html.haml index 9c5f4af26c3..90df81b4dc3 100644 --- a/app/views/merge_requests/_show.html.haml +++ b/app/views/merge_requests/_show.html.haml @@ -21,8 +21,6 @@ = render "merge_requests/show/diffs" if @diffs .status -= render "notes/diff_note_form" - :javascript $(function(){ MergeRequest.init({ diff --git a/app/views/merge_requests/diffs.js.haml b/app/views/merge_requests/diffs.js.haml index 98539985324..c758cf69015 100644 --- a/app/views/merge_requests/diffs.js.haml +++ b/app/views/merge_requests/diffs.js.haml @@ -1,7 +1,3 @@ :plain $(".merge-request-diffs").html("#{escape_javascript(render(partial: "merge_requests/show/diffs"))}"); - $(function(){ - PerLineNotes.init(); - }); - diff --git a/app/views/notes/_common_form.html.haml b/app/views/notes/_common_form.html.haml index a1e87c87d20..cc7eaec307f 100644 --- a/app/views/notes/_common_form.html.haml +++ b/app/views/notes/_common_form.html.haml @@ -8,7 +8,7 @@ = f.hidden_field :noteable_id = f.hidden_field :noteable_type - = f.text_area :note, size: 255, class: 'note-text js-gfm-input' + = f.text_area :note, size: 255, class: 'js-note-text js-gfm-input' #preview-note.preview_note.hide .hint .right Comments are parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}. @@ -16,7 +16,7 @@ .row.note_advanced_opts .span3 - = f.submit 'Add Comment', class: "btn comment-btn submit_note grouped", id: "submit_note" + = f.submit 'Add Comment', class: "btn comment-btn grouped js-comment-button" = link_to 'Preview', preview_project_notes_path(@project), class: 'btn grouped', id: 'preview-link' .span4.notify_opts %h6.left Notify via email: diff --git a/app/views/notes/_create_diff_note.js.haml b/app/views/notes/_create_diff_note.js.haml index a0c065ea4f7..81ade996ea4 100644 --- a/app/views/notes/_create_diff_note.js.haml +++ b/app/views/notes/_create_diff_note.js.haml @@ -1,18 +1,14 @@ - if note.valid? :plain // hide and reset the form - $(".per_line_form").hide(); - $('.line-note-form-holder textarea').val(""); + var form = $("form[rel='#{note.discussion_id}']"); + var row = form.closest("tr"); - // find the reply button for this line - // (might not be there if this is the first note) - var trRpl = $(".js-note-add-to-diff-line[data-noteable-type='#{note.noteable_type}'][data-noteable-id='#{note.noteable_id}'][data-line-code='#{note.line_code}']").closest("tr"); - if (trRpl.size() == 0) { - // find the commented line ... - var trEl = $(".#{note.line_code}").parent(); - // ... and insert the note and the reply button after it - trEl.after("#{escape_javascript(render "notes/diff_notes_with_reply", notes: [note])}"); + // is this the first note? + if (row.is(".js-temp-notes-holder")) { + // insert the note and the reply button after it + row.after("#{escape_javascript(render "notes/diff_notes_with_reply", notes: [note])}"); } else { // instert new note before reply button - trRpl.before("#{escape_javascript(render "notes/diff_note", note: note)}"); + row.find(".notes").append("#{escape_javascript(render "notes/note", note: note)}"); } diff --git a/app/views/notes/_diff_note_form.html.haml b/app/views/notes/_diff_note_form.html.haml index 9210be977f6..91128b91bd2 100644 --- a/app/views/notes/_diff_note_form.html.haml +++ b/app/views/notes/_diff_note_form.html.haml @@ -1,31 +1,26 @@ -%table{style: "display:none;"} - %tr.per_line_form - %td{colspan: 3 } - .line-note-form-holder - = form_for [@project, @note], remote: "true", multipart: true do |f| - %h3.page_title Leave a comment - %div.span10 - -if @note.errors.any? - .alert-message.block-message.error - - @note.errors.full_messages.each do |msg| - %div= msg += form_for [@project, @note], remote: true, html: { multipart: true, class: "new_note new_diff_note js-diff-note-form" } do |f| + .span10 + -if @note.errors.any? + .alert-message.block-message.error + - @note.errors.full_messages.each do |msg| + %div= msg - = f.hidden_field :noteable_id - = f.hidden_field :noteable_type - = f.hidden_field :line_code - = f.text_area :note, size: 255, class: 'line-note-text js-gfm-input' - .note_actions - .buttons - = f.submit 'Add Comment', class: "btn save-btn submit_note submit_inline_note", id: "submit_note" - = link_to "Cancel", "javascript:;", class: "btn hide-button" - .options - %h6.left Notify via email: - .labels - = label_tag :notify do - = check_box_tag :notify, 1, @note.noteable_type != "Commit" - %span Project team + = f.hidden_field :noteable_id + = f.hidden_field :noteable_type + = f.hidden_field :line_code + = f.text_area :note, size: 255, class: 'js-note-text js-gfm-input' + .note_actions + .buttons + = f.submit 'Add Comment', class: "btn save-btn js-comment-button" + %button.btn.js-hide-diff-note-form Cancel + .options + %h6.left Notify via email: + .labels + = label_tag :notify do + = check_box_tag :notify, 1, @note.noteable_type != "Commit" + %span Project team - - if @note.notify_only_author?(current_user) - = label_tag :notify_author do - = check_box_tag :notify_author, 1 , @note.noteable_type == "Commit" - %span Commit author + - if @note.notify_only_author?(current_user) + = label_tag :notify_author do + = check_box_tag :notify_author, 1 , @note.noteable_type == "Commit" + %span Commit author diff --git a/app/views/notes/_diff_note_link.html.haml b/app/views/notes/_diff_note_link.html.haml index d25577eac5a..56eeeb102eb 100644 --- a/app/views/notes/_diff_note_link.html.haml +++ b/app/views/notes/_diff_note_link.html.haml @@ -1,6 +1,9 @@ +- note = @project.notes.new(@comments_target.merge({ line_code: line_code })) = link_to "", - "#", - id: "add-diff-line-note-#{line_code}", - class: "line_note_link js-note-add-to-diff-line", - data: @comments_target.merge({ line_code: line_code }), + "javascript:;", + class: "add-diff-note js-add-diff-note-button", + data: { noteable_type: note.noteable_type, + noteable_id: note.noteable_id, + line_code: note.line_code, + discussion_id: note.discussion_id }, title: "Add a comment to this line" diff --git a/app/views/notes/_diff_notes_with_reply.html.haml b/app/views/notes/_diff_notes_with_reply.html.haml index e3e5b291393..8b12cf11c75 100644 --- a/app/views/notes/_diff_notes_with_reply.html.haml +++ b/app/views/notes/_diff_notes_with_reply.html.haml @@ -1,4 +1,5 @@ -%tr.notes_holder +- note = notes.first # example note +%tr.notes_holder{ data: { :'discussion-id' => note.discussion_id } } %td.notes_line{ colspan: 2 } %span.btn.disabled %i.icon-comment @@ -8,11 +9,12 @@ = render notes -# reply button - - note = notes.first # example note - %button{ class: "btn comment-btn js-note-add-to-diff-line", - data: { line_code: note.line_code, - noteable_type: note.noteable_type, - noteable_id: note.noteable_id }, - title: "Add a comment to this line" } + = link_to "javascript:;", + class: "btn comment-btn js-diff-note-reply-button", + data: { noteable_type: note.noteable_type, + noteable_id: note.noteable_id, + line_code: note.line_code, + discussion_id: note.discussion_id }, + title: "Add a comment to this line" do %i.icon-comment Reply diff --git a/app/views/notes/_notes_with_form.html.haml b/app/views/notes/_notes_with_form.html.haml index 713f8aac668..918b36c4fd8 100644 --- a/app/views/notes/_notes_with_form.html.haml +++ b/app/views/notes/_notes_with_form.html.haml @@ -3,7 +3,9 @@ .notes-status - if can? current_user, :write_note, @project - = render "notes/common_form" + .note-forms.js-note-forms + = render "notes/common_form" + = render "notes/diff_note_form" :javascript $(function(){ diff --git a/app/views/notes/create.js.haml b/app/views/notes/create.js.haml index 9921312e6eb..da7306d441c 100644 --- a/app/views/notes/create.js.haml +++ b/app/views/notes/create.js.haml @@ -2,7 +2,3 @@ = render "create_diff_note", note: @note - else = render "create_common_note", note: @note - --# Enable submit button -:plain - $("#submit_note").removeAttr("disabled"); diff --git a/app/views/notes/index.js.haml b/app/views/notes/index.js.haml index cf46af6523b..ae70dcad289 100644 --- a/app/views/notes/index.js.haml +++ b/app/views/notes/index.js.haml @@ -16,7 +16,3 @@ - if loading_more_notes? :plain NoteList.finishedLoadingMore(); - -- if @has_diff - :plain - PerLineNotes.init(); -- cgit v1.2.1 From 654f10102e051bfcef75add025f6395da58c770d Mon Sep 17 00:00:00 2001 From: Riyad Preukschas Date: Tue, 20 Nov 2012 19:50:12 +0100 Subject: Remove paging from all notes except the wall --- app/contexts/notes/load_context.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/contexts/notes/load_context.rb b/app/contexts/notes/load_context.rb index 9f8299f52f7..4e2f35040fd 100644 --- a/app/contexts/notes/load_context.rb +++ b/app/contexts/notes/load_context.rb @@ -9,11 +9,11 @@ module Notes @notes = case target_type when "commit" - project.commit_notes(project.commit(target_id)).fresh.limit(20) + project.commit_notes(project.commit(target_id)).fresh when "issue" - project.issues.find(target_id).notes.inc_author.fresh.limit(20) + project.issues.find(target_id).notes.inc_author.fresh when "merge_request" - project.merge_requests.find(target_id).mr_and_commit_notes.inc_author.fresh.limit(20) + project.merge_requests.find(target_id).mr_and_commit_notes.inc_author.fresh when "snippet" project.snippets.find(target_id).notes.fresh when "wall" -- cgit v1.2.1 From e8f10f317faca1c87ad6529e3661afa788cb7896 Mon Sep 17 00:00:00 2001 From: Riyad Preukschas Date: Tue, 20 Nov 2012 23:57:01 +0100 Subject: Fix Note validation * remove length restriction on note * add format validation for line_code --- app/models/note.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/models/note.rb b/app/models/note.rb index 17b76615fa2..48916951e3b 100644 --- a/app/models/note.rb +++ b/app/models/note.rb @@ -32,6 +32,7 @@ class Note < ActiveRecord::Base delegate :name, :email, to: :author, prefix: true validates :note, :project, presence: true + validates :line_code, format: { with: /\A\d+_\d+_\d+\Z/ }, allow_blank: true validates :attachment, file_size: { maximum: 10.megabytes.to_i } mount_uploader :attachment, AttachmentUploader -- cgit v1.2.1 From 1319373d58c49eb96c1ec176f3057c2c31750b0e Mon Sep 17 00:00:00 2001 From: Riyad Preukschas Date: Tue, 20 Nov 2012 20:26:46 +0100 Subject: Fix loading notes with empty line_code in Project#commit_notes --- app/models/project.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/project.rb b/app/models/project.rb index 74d981f26d6..ac315c49f34 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -200,7 +200,7 @@ class Project < ActiveRecord::Base end def commit_notes(commit) - notes.where(noteable_id: commit.id, noteable_type: "Commit", line_code: nil) + notes.where(noteable_id: commit.id, noteable_type: "Commit").where('line_code IS NULL OR line_code = ""') end def commit_line_notes(commit) -- cgit v1.2.1 From 494ae87840bf719e5fb4094781cc1dfc179af463 Mon Sep 17 00:00:00 2001 From: Riyad Preukschas Date: Sun, 2 Dec 2012 20:43:39 +0100 Subject: Refactor discussion reply --- app/assets/javascripts/notes.js | 60 ++++---- app/assets/stylesheets/sections/notes.scss | 166 +++++++++++---------- app/controllers/commit_controller.rb | 12 +- app/controllers/issues_controller.rb | 2 + app/controllers/merge_requests_controller.rb | 3 + app/controllers/notes_controller.rb | 14 +- app/controllers/projects_controller.rb | 5 +- app/controllers/snippets_controller.rb | 2 + app/helpers/notes_helper.rb | 7 +- app/views/commit/show.html.haml | 2 +- app/views/issues/show.html.haml | 2 +- app/views/merge_requests/_show.html.haml | 2 +- app/views/merge_requests/show.js.haml | 2 +- app/views/notes/_common_form.html.haml | 7 +- app/views/notes/_create_diff_note.js.haml | 14 -- app/views/notes/_create_discussion_note.js.haml | 13 ++ app/views/notes/_diff_note_form.html.haml | 26 ---- app/views/notes/_diff_notes_with_reply.html.haml | 15 +- app/views/notes/_discussion.html.haml | 10 +- app/views/notes/_discussion_diff.html.haml | 7 +- app/views/notes/_discussion_note_form.html.haml | 28 ++++ app/views/notes/_discussion_reply_button.html.haml | 9 ++ app/views/notes/_notes_with_form.html.haml | 6 +- .../notes/_reversed_notes_with_form.html.haml | 2 +- app/views/notes/create.js.haml | 6 +- app/views/projects/wall.html.haml | 2 +- app/views/snippets/show.html.haml | 2 +- 27 files changed, 229 insertions(+), 197 deletions(-) delete mode 100644 app/views/notes/_create_diff_note.js.haml create mode 100644 app/views/notes/_create_discussion_note.js.haml delete mode 100644 app/views/notes/_diff_note_form.html.haml create mode 100644 app/views/notes/_discussion_note_form.html.haml create mode 100644 app/views/notes/_discussion_reply_button.html.haml diff --git a/app/assets/javascripts/notes.js b/app/assets/javascripts/notes.js index e5c233ef4fc..5c33a6609d6 100644 --- a/app/assets/javascripts/notes.js +++ b/app/assets/javascripts/notes.js @@ -63,18 +63,19 @@ var NoteList = { // reply to diff notes $(document).on("click", - ".js-diff-note-reply-button", - NoteList.replyToDiffNote); + ".js-discussion-reply-button", + NoteList.replyToDiscussionNote); // hide diff note form $(document).on("click", - ".js-hide-diff-note-form", - NoteList.removeDiffNoteForm); + ".js-close-discussion-note-form", + NoteList.removeDiscussionNoteForm); - // do some diff note specific housekeeping when removing a diff note + // do some specific housekeeping when removing a diff or discussion note $(document).on("click", - ".diff_file .js-note-delete", - NoteList.removeDiffNote); + ".diff_file .js-note-delete," + + ".discussion .js-note-delete", + NoteList.removeDiscussionNote); // remove a note (in general) $(document).on("click", @@ -102,14 +103,14 @@ var NoteList = { */ addDiffNote: function(e) { // find the form - var form = $(".js-note-forms .js-diff-note-form"); + var form = $(".js-note-forms .js-discussion-note-form"); var row = $(this).closest("tr"); var nextRow = row.next(); // does it already have notes? if (nextRow.is(".notes_holder")) { - $.proxy(NoteList.replyToDiffNote, - nextRow.find(".js-diff-note-reply-button") + $.proxy(NoteList.replyToDiscussionNote, + nextRow.find(".js-discussion-reply-button") ).call(); } else { // add a notes row and insert the form @@ -117,7 +118,7 @@ var NoteList = { form.clone().appendTo(row.next().find(".notes_content")); // show the form - NoteList.setupDiffNoteForm($(this), row.next().find("form")); + NoteList.setupDiscussionNoteForm($(this), row.next().find("form")); } e.preventDefault(); @@ -131,11 +132,15 @@ var NoteList = { * * Note: must be called before removeNote() */ - removeDiffNote: function() { + removeDiscussionNote: function() { var notes = $(this).closest(".notes"); // check if this is the last note for this line if (notes.find(".note").length === 1) { + // for discussions + notes.closest(".discussion").remove(); + + // for diff lines notes.closest("tr").remove(); } }, @@ -146,15 +151,15 @@ var NoteList = { * Shows the reply button again. * Removes the form and if necessary it's temporary row. */ - removeDiffNoteForm: function(e) { + removeDiscussionNoteForm: function(e) { var form = $(this).closest("form"); var row = form.closest("tr"); // show the reply button (will only work for replys) - form.prev(".js-diff-note-reply-button").show(); + form.prev(".js-discussion-reply-button").show(); if (row.is(".js-temp-notes-holder")) { - // remove temporary row + // remove temporary row for diff lines row.remove(); } else { // only remove the form @@ -179,10 +184,9 @@ var NoteList = { * * Shows the note form below the notes. */ - replyToDiffNote: function() { + replyToDiscussionNote: function() { // find the form - var form = $(".js-note-forms .js-diff-note-form"); - + var form = $(".js-note-forms .js-discussion-note-form"); // hide reply button $(this).hide(); @@ -190,7 +194,7 @@ var NoteList = { form.clone().insertAfter($(this)); // show the form - NoteList.setupDiffNoteForm($(this), $(this).next("form")); + NoteList.setupDiscussionNoteForm($(this), $(this).next("form")); }, /** @@ -201,7 +205,7 @@ var NoteList = { * Note: "this" must have the "discussionId", "lineCode", "noteableType" and * "noteableId" data attributes set. */ - setupDiffNoteForm: function(data_holder, form) { + setupDiscussionNoteForm: function(data_holder, form) { // setup note target form.attr("rel", data_holder.data("discussionId")); form.find("#note_line_code").val(data_holder.data("lineCode")); @@ -210,10 +214,10 @@ var NoteList = { // setup interaction disableButtonIfEmptyField(form.find(".js-note-text"), form.find(".js-comment-button")); - setupGfmAutoComplete(); + GitLab.GfmAutoComplete.setup(); // cleanup after successfully creating a diff note - form.on("ajax:success", NoteList.removeDiffNoteForm); + form.on("ajax:success", NoteList.removeDiscussionNoteForm); form.show(); }, @@ -249,11 +253,11 @@ var NoteList = { this.bottom_id = newNoteIds.last(); $("#notes-list").html(html); - // init infinite scrolling - this.initLoadMore(); - - // init getting new notes if (this.reversed) { + // init infinite scrolling + this.initLoadMore(); + + // init getting new notes this.initRefreshNew(); } }, @@ -377,9 +381,9 @@ var NoteList = { appendNewNote: function(id, html) { if (this.reversed) { - $("#new-notes-list").prepend(html); + $("#notes-list").prepend(html); } else { - $("#new-notes-list").append(html); + $("#notes-list").append(html); } this.updateVotes(); }, diff --git a/app/assets/stylesheets/sections/notes.scss b/app/assets/stylesheets/sections/notes.scss index 97739017c2c..a32ecf0c933 100644 --- a/app/assets/stylesheets/sections/notes.scss +++ b/app/assets/stylesheets/sections/notes.scss @@ -46,9 +46,12 @@ ul.notes { @extend .borders; background-color: #F9F9F9; } - .diff_file .note { - border-bottom: 0px; - padding: 0px; + .diff_file .notes { + /* reset */ + background: inherit; + border: none; + @include box-shadow(none); + } .discussion-hidden .note { @extend .cgray; @@ -59,6 +62,9 @@ ul.notes { border-color: #ddd; padding: 8px; } + .reply-btn { + margin-top: 8px; + } } } @@ -92,7 +98,7 @@ ul.notes { } } -.diff_file tr.notes_holder { +.diff_file .notes_holder { font-family: $sansFontFamily; font-size: 13px; line-height: 18px; @@ -112,38 +118,9 @@ ul.notes { } } - .comment-btn { + .reply-btn { margin-top: 8px; } - - // TODO: start cleanup - form { - // hide it by default - display: none; - margin: 8px 0; - - .note_actions { - margin:0; - padding-top: 10px; - - .buttons { - float:left; - width:300px; - } - .options { - .labels { - float:left; - padding-left:10px; - label { - padding: 6px 0; - margin: 0; - width:120px; - } - } - } - } - } - // TODO: end cleanup } /** @@ -185,6 +162,7 @@ ul.notes { top: 0; } +// TODO: start cleaup .issue_notes, .wiki_notes { .note_content { @@ -193,6 +171,7 @@ ul.notes { } } +/* for loading indicator */ .notes-status { margin: 18px; } @@ -205,6 +184,7 @@ p.notify_controls input{ p.notify_controls span{ font-weight: 700; } +// TODO: end cleaup /** * add line note button on the side of diffs @@ -242,56 +222,49 @@ p.notify_controls span{ * Note Forms */ -.comment-btn { +.comment-btn, +.reply-btn { @extend .save-btn; } +.new_discussion_note { + // hide it by default + display: none; + margin: 8px 5px 8px 0; + + // TODO: start cleanup + .note_actions { + margin:0; + padding-top: 10px; + + .buttons { + float:left; + width:300px; + } + .options { + .labels { + float:left; + padding-left:10px; + label { + padding: 6px 0; + margin: 0; + width:120px; + } + } + } + } + // TODO: end cleanup +} .new_note { textarea { height:80px; width:99%; font-size:14px; } -} -.note-forms { - .new_diff_note { - display: none; - } -} - -#new_note { + // TODO: start cleanup .attach_holder { display:none; } -} - -.preview_note { - margin: 2px; - border: 1px solid #ddd; - padding: 10px; - min-height: 60px; - background:#f5f5f5; -} - -form.new_note { - .input-file { - font: 500px monospace; - opacity: 0; - filter: alpha(opacity=0); - position: absolute; - z-index: 1; - top: 0; - right: 0; - padding: 0; - margin: 0; - } - - .note_advanced_opts { - h6 { - line-height: 32px; - padding-right: 15px; - } - } .attachments { position: relative; @@ -301,18 +274,17 @@ form.new_note { margin:0 0 5px !important; .input_file { - .file_upload { - position: absolute; - right: 14px; - top: 7px; - } - .file_name { line-height: 30px; width: 240px; height: 28px; overflow: hidden; } + .file_upload { + position: absolute; + right:14px; + top:7px; + } .input-file { width: 260px; height: 41px; @@ -320,9 +292,41 @@ form.new_note { } } } + .input-file { + font: 500px monospace; + opacity:0; + filter: alpha(opacity=0); + position: absolute; + z-index: 1; + top:0; + right:0; + padding:0; + margin: 0; + } + .note_advanced_opts { + h6 { + line-height: 32px; + padding-right: 15px; + } + } + .note-text { + border: 1px solid #aaa; + box-shadow:none; + } + // TODO: end cleanup +} + +// hide the new discussion note form template +.note-forms { + .new_discussion_note { + display: none; + } } -.note-text { - border: 1px solid #aaa; - box-shadow: none; +.preview_note { + margin: 2px; + border: 1px solid #ddd; + padding: 10px; + min-height: 60px; + background:#f5f5f5; } diff --git a/app/controllers/commit_controller.rb b/app/controllers/commit_controller.rb index ebc27772f9a..4fbfe205d3f 100644 --- a/app/controllers/commit_controller.rb +++ b/app/controllers/commit_controller.rb @@ -13,10 +13,14 @@ class CommitController < ProjectResourceController @commit = result[:commit] git_not_found! unless @commit - @suppress_diff = result[:suppress_diff] - @note = result[:note] - @line_notes = result[:line_notes] - @notes_count = result[:notes_count] + @suppress_diff = result[:suppress_diff] + + @note = result[:note] + @line_notes = result[:line_notes] + @notes_count = result[:notes_count] + @target_type = :commit + @target_id = @commit.id + @comments_allowed = @reply_allowed = true @comments_target = { noteable_type: 'Commit', noteable_id: @commit.id } diff --git a/app/controllers/issues_controller.rb b/app/controllers/issues_controller.rb index 0f28fc3a111..443763cd2dd 100644 --- a/app/controllers/issues_controller.rb +++ b/app/controllers/issues_controller.rb @@ -38,6 +38,8 @@ class IssuesController < ProjectResourceController def show @note = @project.notes.new(noteable: @issue) + @target_type = :issue + @target_id = @issue.id respond_to do |format| format.html diff --git a/app/controllers/merge_requests_controller.rb b/app/controllers/merge_requests_controller.rb index 24f4239e520..841e8085ed3 100644 --- a/app/controllers/merge_requests_controller.rb +++ b/app/controllers/merge_requests_controller.rb @@ -21,6 +21,9 @@ class MergeRequestsController < ProjectResourceController end def show + @target_type = :merge_request + @target_id = @merge_request.id + respond_to do |format| format.html format.js diff --git a/app/controllers/notes_controller.rb b/app/controllers/notes_controller.rb index 4f8b7bb9da3..e04a61b2905 100644 --- a/app/controllers/notes_controller.rb +++ b/app/controllers/notes_controller.rb @@ -6,13 +6,11 @@ class NotesController < ProjectResourceController respond_to :js def index - @target_note = Note.new(noteable_type: params[:target_type].camelize, - noteable_id: params[:target_id]) - @target = @target_note.noteable @notes = Notes::LoadContext.new(project, current_user, params).execute + @target_type = params[:target_type].camelize + @target_id = params[:target_id] if params[:target_type] == "merge_request" - @mixed_targets = true @discussions = discussions_from_notes end @@ -21,6 +19,8 @@ class NotesController < ProjectResourceController def create @note = Notes::CreateContext.new(project, current_user, params).execute + @target_type = params[:target_type].camelize + @target_id = params[:target_id] respond_to do |format| format.html {redirect_to :back} @@ -58,7 +58,7 @@ class NotesController < ProjectResourceController next if discussion_ids.include?(note.discussion_id) # don't group notes for the main target - if for_main_target?(note) + if note_for_main_target?(note) discussions << [note] else discussions << discussion_notes_for(note) @@ -70,7 +70,7 @@ class NotesController < ProjectResourceController end # Helps to distinguish e.g. commit notes in mr notes list - def for_main_target?(note) - !@mixed_targets || (@target.class.name == note.noteable_type && !note.for_diff_line?) + def note_for_main_target?(note) + @target_type.camelize == note.noteable_type && !note.for_diff_line? end end diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index a6e7f1f93fb..1165729f9f8 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -75,7 +75,10 @@ class ProjectsController < ProjectResourceController def wall return render_404 unless @project.wall_enabled - @note = Note.new + + @target_type = :wall + @target_id = nil + @note = @project.notes.new respond_to do |format| format.html diff --git a/app/controllers/snippets_controller.rb b/app/controllers/snippets_controller.rb index 7324a4594eb..b0438222461 100644 --- a/app/controllers/snippets_controller.rb +++ b/app/controllers/snippets_controller.rb @@ -50,6 +50,8 @@ class SnippetsController < ProjectResourceController def show @note = @project.notes.new(noteable: @snippet) + @target_type = :snippet + @target_id = @snippet.id end def destroy diff --git a/app/helpers/notes_helper.rb b/app/helpers/notes_helper.rb index 02dec2a043e..e82537a336f 100644 --- a/app/helpers/notes_helper.rb +++ b/app/helpers/notes_helper.rb @@ -1,7 +1,12 @@ module NotesHelper # Helps to distinguish e.g. commit notes in mr notes list def note_for_main_target?(note) - !@mixed_targets || (@target.class.name == note.noteable_type && !note.for_diff_line?) + @target_type.camelize == note.noteable_type && !note.for_diff_line? + end + + def note_target_fields + hidden_field_tag(:target_type, @target_type) + + hidden_field_tag(:target_id, @target_id) end def link_to_commit_diff_line_note(note) diff --git a/app/views/commit/show.html.haml b/app/views/commit/show.html.haml index cef6b2f5bd5..5ba43f951dc 100644 --- a/app/views/commit/show.html.haml +++ b/app/views/commit/show.html.haml @@ -1,6 +1,6 @@ = render "commits/commit_box" = render "commits/diffs", diffs: @commit.diffs -= render "notes/notes_with_form", tid: @commit.id, tt: "commit" += render "notes/notes_with_form" :javascript $(function(){ diff --git a/app/views/issues/show.html.haml b/app/views/issues/show.html.haml index 9114febdd02..a52d1134acc 100644 --- a/app/views/issues/show.html.haml +++ b/app/views/issues/show.html.haml @@ -61,4 +61,4 @@ = markdown @issue.description -.issue_notes.voting_notes#notes= render "notes/notes_with_form", tid: @issue.id, tt: "issue" +.issue_notes.voting_notes#notes= render "notes/notes_with_form" diff --git a/app/views/merge_requests/_show.html.haml b/app/views/merge_requests/_show.html.haml index 90df81b4dc3..138f65105f7 100644 --- a/app/views/merge_requests/_show.html.haml +++ b/app/views/merge_requests/_show.html.haml @@ -16,7 +16,7 @@ Diff .merge_request_notes.voting_notes#notes{ class: (controller.action_name == 'show') ? "" : "hide" } - = render("notes/notes_with_form", tid: @merge_request.id, tt: "merge_request") + = render "notes/notes_with_form" .merge-request-diffs = render "merge_requests/show/diffs" if @diffs .status diff --git a/app/views/merge_requests/show.js.haml b/app/views/merge_requests/show.js.haml index f44ccbb5127..7f423c786de 100644 --- a/app/views/merge_requests/show.js.haml +++ b/app/views/merge_requests/show.js.haml @@ -1,2 +1,2 @@ :plain - $(".merge-request-notes").html("#{escape_javascript(render notes/notes_with_form", tid: @merge_request.id, tt: "merge_request")}"); + $(".merge-request-notes").html("#{escape_javascript(render notes/notes_with_form")}"); diff --git a/app/views/notes/_common_form.html.haml b/app/views/notes/_common_form.html.haml index cc7eaec307f..7c25bf73296 100644 --- a/app/views/notes/_common_form.html.haml +++ b/app/views/notes/_common_form.html.haml @@ -1,13 +1,16 @@ .note-form-holder = form_for [@project, @note], remote: "true", multipart: true do |f| + + = note_target_fields + = f.hidden_field :noteable_id + = f.hidden_field :noteable_type + %h3.page_title Leave a comment -if @note.errors.any? .alert-message.block-message.error - @note.errors.full_messages.each do |msg| %div= msg - = f.hidden_field :noteable_id - = f.hidden_field :noteable_type = f.text_area :note, size: 255, class: 'js-note-text js-gfm-input' #preview-note.preview_note.hide .hint diff --git a/app/views/notes/_create_diff_note.js.haml b/app/views/notes/_create_diff_note.js.haml deleted file mode 100644 index 81ade996ea4..00000000000 --- a/app/views/notes/_create_diff_note.js.haml +++ /dev/null @@ -1,14 +0,0 @@ -- if note.valid? - :plain - // hide and reset the form - var form = $("form[rel='#{note.discussion_id}']"); - var row = form.closest("tr"); - - // is this the first note? - if (row.is(".js-temp-notes-holder")) { - // insert the note and the reply button after it - row.after("#{escape_javascript(render "notes/diff_notes_with_reply", notes: [note])}"); - } else { - // instert new note before reply button - row.find(".notes").append("#{escape_javascript(render "notes/note", note: note)}"); - } diff --git a/app/views/notes/_create_discussion_note.js.haml b/app/views/notes/_create_discussion_note.js.haml new file mode 100644 index 00000000000..968ef0cfbee --- /dev/null +++ b/app/views/notes/_create_discussion_note.js.haml @@ -0,0 +1,13 @@ +- if note.valid? + :plain + // is this the first note of discussion? + var row = $("form[rel='#{note.discussion_id}']").closest("tr"); + if (row.is(".js-temp-notes-holder")) { + // insert the note and the reply button after it + row.after("#{escape_javascript(render "notes/diff_notes_with_reply", notes: [note])}"); + // will be added again below + row.next().find(".note").remove(); + } + + // append new note to all discussions + $(".notes[rel='#{note.discussion_id}']").append("#{escape_javascript(render "notes/note", note: note)}"); diff --git a/app/views/notes/_diff_note_form.html.haml b/app/views/notes/_diff_note_form.html.haml deleted file mode 100644 index 91128b91bd2..00000000000 --- a/app/views/notes/_diff_note_form.html.haml +++ /dev/null @@ -1,26 +0,0 @@ -= form_for [@project, @note], remote: true, html: { multipart: true, class: "new_note new_diff_note js-diff-note-form" } do |f| - .span10 - -if @note.errors.any? - .alert-message.block-message.error - - @note.errors.full_messages.each do |msg| - %div= msg - - = f.hidden_field :noteable_id - = f.hidden_field :noteable_type - = f.hidden_field :line_code - = f.text_area :note, size: 255, class: 'js-note-text js-gfm-input' - .note_actions - .buttons - = f.submit 'Add Comment', class: "btn save-btn js-comment-button" - %button.btn.js-hide-diff-note-form Cancel - .options - %h6.left Notify via email: - .labels - = label_tag :notify do - = check_box_tag :notify, 1, @note.noteable_type != "Commit" - %span Project team - - - if @note.notify_only_author?(current_user) - = label_tag :notify_author do - = check_box_tag :notify_author, 1 , @note.noteable_type == "Commit" - %span Commit author diff --git a/app/views/notes/_diff_notes_with_reply.html.haml b/app/views/notes/_diff_notes_with_reply.html.haml index 8b12cf11c75..0808f86b090 100644 --- a/app/views/notes/_diff_notes_with_reply.html.haml +++ b/app/views/notes/_diff_notes_with_reply.html.haml @@ -1,20 +1,11 @@ - note = notes.first # example note -%tr.notes_holder{ data: { :'discussion-id' => note.discussion_id } } +%tr.notes_holder %td.notes_line{ colspan: 2 } %span.btn.disabled %i.icon-comment = notes.count %td.notes_content - %ul.notes + %ul.notes{ rel: note.discussion_id } = render notes - -# reply button - = link_to "javascript:;", - class: "btn comment-btn js-diff-note-reply-button", - data: { noteable_type: note.noteable_type, - noteable_id: note.noteable_id, - line_code: note.line_code, - discussion_id: note.discussion_id }, - title: "Add a comment to this line" do - %i.icon-comment - Reply + = render "notes/discussion_reply_button", note: note diff --git a/app/views/notes/_discussion.html.haml b/app/views/notes/_discussion.html.haml index 8c050216b82..7e9d366e286 100644 --- a/app/views/notes/_discussion.html.haml +++ b/app/views/notes/_discussion.html.haml @@ -30,11 +30,13 @@ ago .discussion-body - if note.for_diff_line? - .diff_file.content - = render "notes/discussion_diff", discussion_notes: discussion_notes, note: note + .content + .diff_file= render "notes/discussion_diff", discussion_notes: discussion_notes, note: note - else - .notes.content - = render discussion_notes + .content + .notes{ rel: discussion_notes.first.discussion_id } + = render discussion_notes + = render "notes/discussion_reply_button", note: discussion_notes.first -# will be shown when the other one is hidden .discussion-hidden.content.hide diff --git a/app/views/notes/_discussion_diff.html.haml b/app/views/notes/_discussion_diff.html.haml index 544435af6ba..78f06f78f69 100644 --- a/app/views/notes/_discussion_diff.html.haml +++ b/app/views/notes/_discussion_diff.html.haml @@ -1,10 +1,11 @@ - diff = note.diff .diff_file_header - %i.icon-file - if diff.deleted_file - %span{id: "#{diff.a_path}"}= diff.a_path + %span= diff.old_path - else - %span{id: "#{diff.b_path}"}= diff.b_path + %span= diff.new_path + - if diff.a_mode && diff.b_mode && diff.a_mode != diff.b_mode + %span.file-mode= "#{diff.a_mode} → #{diff.b_mode}" %br/ .diff_file_content %table diff --git a/app/views/notes/_discussion_note_form.html.haml b/app/views/notes/_discussion_note_form.html.haml new file mode 100644 index 00000000000..045bfdbf114 --- /dev/null +++ b/app/views/notes/_discussion_note_form.html.haml @@ -0,0 +1,28 @@ += form_for [@project, @note], remote: true, html: { multipart: true, class: "new_note new_discussion_note js-discussion-note-form" } do |f| + + = note_target_fields + = f.hidden_field :line_code + = f.hidden_field :noteable_id + = f.hidden_field :noteable_type + + -if @note.errors.any? + .alert-message.block-message.error + - @note.errors.full_messages.each do |msg| + %div= msg + + = f.text_area :note, size: 255, class: 'js-note-text js-gfm-input' + .note_actions + .buttons + = f.submit 'Add Comment', class: "btn comment-btn js-comment-button" + %button.btn.js-close-discussion-note-form Cancel + .options + %h6.left Notify via email: + .labels + = label_tag :notify do + = check_box_tag :notify, 1, @note.noteable_type != "Commit" + %span Project team + + - if @note.notify_only_author?(current_user) + = label_tag :notify_author do + = check_box_tag :notify_author, 1 , @note.noteable_type == "Commit" + %span Commit author diff --git a/app/views/notes/_discussion_reply_button.html.haml b/app/views/notes/_discussion_reply_button.html.haml new file mode 100644 index 00000000000..15b68560955 --- /dev/null +++ b/app/views/notes/_discussion_reply_button.html.haml @@ -0,0 +1,9 @@ += link_to "javascript:;", + class: "btn reply-btn js-discussion-reply-button", + data: { noteable_type: note.noteable_type, + noteable_id: note.noteable_id, + line_code: note.line_code, + discussion_id: note.discussion_id }, + title: "Add a reply" do + %i.icon-comment + Reply diff --git a/app/views/notes/_notes_with_form.html.haml b/app/views/notes/_notes_with_form.html.haml index 918b36c4fd8..3e3918412bb 100644 --- a/app/views/notes/_notes_with_form.html.haml +++ b/app/views/notes/_notes_with_form.html.haml @@ -1,13 +1,11 @@ %ul#notes-list.notes -%ul#new-notes-list.notes -.notes-status - if can? current_user, :write_note, @project .note-forms.js-note-forms = render "notes/common_form" - = render "notes/diff_note_form" + = render "notes/discussion_note_form" :javascript $(function(){ - NoteList.init("#{tid}", "#{tt}", "#{project_notes_path(@project)}"); + NoteList.init("#{@target_id}", "#{@target_type}", "#{project_notes_path(@project)}"); }); diff --git a/app/views/notes/_reversed_notes_with_form.html.haml b/app/views/notes/_reversed_notes_with_form.html.haml index 9c28d015c72..50fdad2ce1f 100644 --- a/app/views/notes/_reversed_notes_with_form.html.haml +++ b/app/views/notes/_reversed_notes_with_form.html.haml @@ -7,5 +7,5 @@ :javascript $(function(){ - NoteList.init("#{tid}", "#{tt}", "#{project_notes_path(@project)}"); + NoteList.init("#{@target_id}", "#{@target_type}", "#{project_notes_path(@project)}"); }); diff --git a/app/views/notes/create.js.haml b/app/views/notes/create.js.haml index da7306d441c..03aec54b018 100644 --- a/app/views/notes/create.js.haml +++ b/app/views/notes/create.js.haml @@ -1,4 +1,4 @@ -- if @note.line_code - = render "create_diff_note", note: @note -- else +- if note_for_main_target?(@note) = render "create_common_note", note: @note +- else + = render "create_discussion_note", note: @note diff --git a/app/views/projects/wall.html.haml b/app/views/projects/wall.html.haml index 591a8cd06d4..82b565def43 100644 --- a/app/views/projects/wall.html.haml +++ b/app/views/projects/wall.html.haml @@ -1,2 +1,2 @@ %div.wall_page - = render "notes/reversed_notes_with_form", tid: nil, tt: "wall" + = render "notes/reversed_notes_with_form" diff --git a/app/views/snippets/show.html.haml b/app/views/snippets/show.html.haml index f3e01928077..5b9d3d5d623 100644 --- a/app/views/snippets/show.html.haml +++ b/app/views/snippets/show.html.haml @@ -8,4 +8,4 @@ %br %div= render 'blob' -%div#notes= render "notes/notes_with_form", tid: @snippet.id, tt: "snippet" +%div#notes= render "notes/notes_with_form" -- cgit v1.2.1 From d9b15fc17d6d7feb0119fb8c900a0ee4e6f09a3a Mon Sep 17 00:00:00 2001 From: Riyad Preukschas Date: Wed, 21 Nov 2012 23:18:12 +0100 Subject: Crop and rename the add diff note image --- app/assets/images/comment_add.png | Bin 781 -> 0 bytes app/assets/images/diff_note_add.png | Bin 0 -> 691 bytes app/assets/stylesheets/sections/notes.scss | 15 ++++++++------- 3 files changed, 8 insertions(+), 7 deletions(-) delete mode 100644 app/assets/images/comment_add.png create mode 100644 app/assets/images/diff_note_add.png diff --git a/app/assets/images/comment_add.png b/app/assets/images/comment_add.png deleted file mode 100644 index 836557ac846..00000000000 Binary files a/app/assets/images/comment_add.png and /dev/null differ diff --git a/app/assets/images/diff_note_add.png b/app/assets/images/diff_note_add.png new file mode 100644 index 00000000000..8ec15b701fc Binary files /dev/null and b/app/assets/images/diff_note_add.png differ diff --git a/app/assets/stylesheets/sections/notes.scss b/app/assets/stylesheets/sections/notes.scss index a32ecf0c933..2535d9f46ad 100644 --- a/app/assets/stylesheets/sections/notes.scss +++ b/app/assets/stylesheets/sections/notes.scss @@ -191,14 +191,14 @@ p.notify_controls span{ */ .diff_file tr.line_holder { .add-diff-note { - position:absolute; - margin-left:-70px; - margin-top:-10px; - z-index:10; - background: url("comment_add.png") no-repeat left 0; - width:32px; - height:32px; + background: url("diff_note_add.png") no-repeat left 0; + height: 22px; + margin-left: -65px; + position: absolute; + width: 22px; + z-index: 10; + // "hide" it by default opacity: 0.0; filter: alpha(opacity=0); @@ -208,6 +208,7 @@ p.notify_controls span{ } } + // "show" the icon also if we just hover somwhere over the line &:hover > td { background: $hover !important; -- cgit v1.2.1 From fac4e3f2e5ea62ed4b92722f5eb1a650ccccf4b1 Mon Sep 17 00:00:00 2001 From: Riyad Preukschas Date: Thu, 22 Nov 2012 00:23:26 +0100 Subject: Reformat notes JS --- app/assets/javascripts/notes.js | 366 +++++++++++++++++++--------------------- 1 file changed, 177 insertions(+), 189 deletions(-) diff --git a/app/assets/javascripts/notes.js b/app/assets/javascripts/notes.js index 5c33a6609d6..7f4bd330839 100644 --- a/app/assets/javascripts/notes.js +++ b/app/assets/javascripts/notes.js @@ -9,85 +9,84 @@ var NoteList = { loading_more_disabled: false, reversed: false, - init: - function(tid, tt, path) { - this.notes_path = path + ".js"; - this.target_id = tid; - this.target_type = tt; - this.reversed = $("#notes-list").is(".reversed"); - this.target_params = "target_type=" + this.target_type + "&target_id=" + this.target_id; - - if(this.reversed) { - var textarea = $(".note-text"); - $('.note_advanced_opts').hide(); - textarea.css("height", "40px"); - textarea.on("focus", function(){ - $(this).css("height", "80px"); - $('.note_advanced_opts').show(); - }); - } + init: function(tid, tt, path) { + this.notes_path = path + ".js"; + this.target_id = tid; + this.target_type = tt; + this.reversed = $("#notes-list").is(".reversed"); + this.target_params = "target_type=" + this.target_type + "&target_id=" + this.target_id; + + if(this.reversed) { + var textarea = $(".note-text"); + $('.note_advanced_opts').hide(); + textarea.css("height", "40px"); + textarea.on("focus", function(){ + $(this).css("height", "80px"); + $('.note_advanced_opts').show(); + }); + } - // get initial set of notes - this.getContent(); + // get initial set of notes + this.getContent(); - disableButtonIfEmptyField(".js-note-text", ".js-comment-button"); + disableButtonIfEmptyField(".js-note-text", ".js-comment-button"); - $("#note_attachment").change(function(e){ - var val = $('.input-file').val(); - var filename = val.replace(/^.*[\\\/]/, ''); - $(".file_name").text(filename); - }); + $("#note_attachment").change(function(e){ + var val = $('.input-file').val(); + var filename = val.replace(/^.*[\\\/]/, ''); + $(".file_name").text(filename); + }); - // Setup note preview - $(document).on('click', '#preview-link', function(e) { - $('#preview-note').text('Loading...'); - - $(this).text($(this).text() === "Edit" ? "Preview" : "Edit"); - - var note_text = $('#note_note').val(); - - if(note_text.trim().length === 0) { - $('#preview-note').text('Nothing to preview.'); - } else { - $.post($(this).attr('href'), {note: note_text}).success(function(data) { - $('#preview-note').html(data); - }); - } - - $('#preview-note, #note_note').toggle(); - });+ - - $(document).on("click", - ".js-add-diff-note-button", - NoteList.addDiffNote); - - // reply to diff notes - $(document).on("click", - ".js-discussion-reply-button", - NoteList.replyToDiscussionNote); - - // hide diff note form - $(document).on("click", - ".js-close-discussion-note-form", - NoteList.removeDiscussionNoteForm); - - // do some specific housekeeping when removing a diff or discussion note - $(document).on("click", - ".diff_file .js-note-delete," + - ".discussion .js-note-delete", - NoteList.removeDiscussionNote); - - // remove a note (in general) - $(document).on("click", - ".js-note-delete", - NoteList.removeNote); - - // clean up previews for forms - $(document).on("ajax:complete", ".note-form-holder", function(){ - $(this).find('#preview-note').hide(); - $(this).find('#note_note').show(); - }); - }, + // Setup note preview + $(document).on('click', '#preview-link', function(e) { + $('#preview-note').text('Loading...'); + + $(this).text($(this).text() === "Edit" ? "Preview" : "Edit"); + + var note_text = $('#note_note').val(); + + if(note_text.trim().length === 0) { + $('#preview-note').text('Nothing to preview.'); + } else { + $.post($(this).attr('href'), {note: note_text}).success(function(data) { + $('#preview-note').html(data); + }); + } + + $('#preview-note, #note_note').toggle(); + });+ + + $(document).on("click", + ".js-add-diff-note-button", + NoteList.addDiffNote); + + // reply to diff notes + $(document).on("click", + ".js-discussion-reply-button", + NoteList.replyToDiscussionNote); + + // hide diff note form + $(document).on("click", + ".js-close-discussion-note-form", + NoteList.removeDiscussionNoteForm); + + // do some specific housekeeping when removing a diff or discussion note + $(document).on("click", + ".diff_file .js-note-delete," + + ".discussion .js-note-delete", + NoteList.removeDiscussionNote); + + // remove a note (in general) + $(document).on("click", + ".js-note-delete", + NoteList.removeNote); + + // clean up previews for forms + $(document).on("ajax:complete", ".note-form-holder", function(){ + $(this).find('#preview-note').hide(); + $(this).find('#note_note').show(); + }); + }, /** @@ -232,35 +231,33 @@ var NoteList = { /** * Gets an inital set of notes. */ - getContent: - function() { - $.ajax({ - url: this.notes_path, - data: this.target_params, - complete: function(){ $('.notes-status').removeClass("loading")}, - beforeSend: function() { $('.notes-status').addClass("loading") }, - dataType: "script" - }); - }, + getContent: function() { + $.ajax({ + url: this.notes_path, + data: this.target_params, + complete: function(){ $('.notes-status').removeClass("loading")}, + beforeSend: function() { $('.notes-status').addClass("loading") }, + dataType: "script" + }); + }, /** * Called in response to getContent(). * Replaces the content of #notes-list with the given html. */ - setContent: - function(newNoteIds, html) { - this.top_id = newNoteIds.first(); - this.bottom_id = newNoteIds.last(); - $("#notes-list").html(html); - - if (this.reversed) { - // init infinite scrolling - this.initLoadMore(); - - // init getting new notes - this.initRefreshNew(); - } - }, + setContent: function(newNoteIds, html) { + this.top_id = newNoteIds.first(); + this.bottom_id = newNoteIds.last(); + $("#notes-list").html(html); + + if (this.reversed) { + // init infinite scrolling + this.initLoadMore(); + + // init getting new notes + this.initRefreshNew(); + } + }, /** @@ -274,66 +271,62 @@ var NoteList = { /** * Initializes loading more notes when scrolling to the bottom of the page. */ - initLoadMore: - function() { - $(document).endlessScroll({ - bottomPixels: 400, - fireDelay: 1000, - fireOnce:true, - ceaseFire: function() { - return NoteList.loading_more_disabled; - }, - callback: function(i) { - NoteList.getMore(); - } - }); - }, + initLoadMore: function() { + $(document).endlessScroll({ + bottomPixels: 400, + fireDelay: 1000, + fireOnce:true, + ceaseFire: function() { + return NoteList.loading_more_disabled; + }, + callback: function(i) { + NoteList.getMore(); + } + }); + }, /** * Gets an additional set of notes. */ - getMore: - function() { - // only load more notes if there are no "new" notes - $('.loading').show(); - $.ajax({ - url: this.notes_path, - data: this.target_params + "&loading_more=1&" + (this.reversed ? "before_id" : "after_id") + "=" + this.bottom_id, - complete: function(){ $('.notes-status').removeClass("loading")}, - beforeSend: function() { $('.notes-status').addClass("loading") }, - dataType: "script" - }); - }, + getMore: function() { + // only load more notes if there are no "new" notes + $('.loading').show(); + $.ajax({ + url: this.notes_path, + data: this.target_params + "&loading_more=1&" + (this.reversed ? "before_id" : "after_id") + "=" + this.bottom_id, + complete: function(){ $('.notes-status').removeClass("loading")}, + beforeSend: function() { $('.notes-status').addClass("loading") }, + dataType: "script" + }); + }, /** * Called in response to getMore(). * Append notes to #notes-list. */ - appendMoreNotes: - function(newNoteIds, html) { - var lastNewNoteId = newNoteIds.last(); - if(lastNewNoteId != this.bottom_id) { - this.bottom_id = lastNewNoteId; - $("#notes-list").append(html); - } - }, + appendMoreNotes: function(newNoteIds, html) { + var lastNewNoteId = newNoteIds.last(); + if(lastNewNoteId != this.bottom_id) { + this.bottom_id = lastNewNoteId; + $("#notes-list").append(html); + } + }, /** * Called in response to getMore(). * Disables loading more notes when scrolling to the bottom of the page. * Initalizes refreshing new notes. */ - finishedLoadingMore: - function() { - this.loading_more_disabled = true; + finishedLoadingMore: function() { + this.loading_more_disabled = true; - // from now on only get new notes - if (!this.reversed) { - this.initRefreshNew(); - } - // make sure we are up to date - this.updateVotes(); - }, + // from now on only get new notes + if (!this.reversed) { + this.initRefreshNew(); + } + // make sure we are up to date + this.updateVotes(); + }, /** @@ -348,45 +341,41 @@ var NoteList = { /** * Initializes getting new notes every n seconds. */ - initRefreshNew: - function() { - setInterval("NoteList.getNew()", 10000); - }, + initRefreshNew: function() { + setInterval("NoteList.getNew()", 10000); + }, /** * Gets the new set of notes. */ - getNew: - function() { - $.ajax({ - url: this.notes_path, - data: this.target_params + "&loading_new=1&after_id=" + (this.reversed ? this.top_id : this.bottom_id), - dataType: "script" - }); - }, + getNew: function() { + $.ajax({ + url: this.notes_path, + data: this.target_params + "&loading_new=1&after_id=" + (this.reversed ? this.top_id : this.bottom_id), + dataType: "script" + }); + }, /** * Called in response to getNew(). * Replaces the content of #new-notes-list with the given html. */ - replaceNewNotes: - function(newNoteIds, html) { - $("#new-notes-list").html(html); - this.updateVotes(); - }, + replaceNewNotes: function(newNoteIds, html) { + $("#new-notes-list").html(html); + this.updateVotes(); + }, /** * Adds a single note to #new-notes-list. */ - appendNewNote: - function(id, html) { - if (this.reversed) { - $("#notes-list").prepend(html); - } else { - $("#notes-list").append(html); - } - this.updateVotes(); - }, + appendNewNote: function(id, html) { + if (this.reversed) { + $("#notes-list").prepend(html); + } else { + $("#notes-list").append(html); + } + this.updateVotes(); + }, /** * Recalculates the votes and updates them (if they are displayed at all). @@ -396,25 +385,24 @@ var NoteList = { * Might produce inaccurate results when not all notes have been loaded and a * recalculation is triggered (e.g. when deleting a note). */ - updateVotes: - function() { - var votes = $("#votes .votes"); - var notes = $("#notes-list, #new-notes-list").find(".note .vote"); - - // only update if there is a vote display - if (votes.size()) { - var upvotes = notes.filter(".upvote").size(); - var downvotes = notes.filter(".downvote").size(); - var votesCount = upvotes + downvotes; - var upvotesPercent = votesCount ? (100.0 / votesCount * upvotes) : 0; - var downvotesPercent = votesCount ? (100.0 - upvotesPercent) : 0; - - // change vote bar lengths - votes.find(".bar-success").css("width", upvotesPercent+"%"); - votes.find(".bar-danger").css("width", downvotesPercent+"%"); - // replace vote numbers - votes.find(".upvotes").text(votes.find(".upvotes").text().replace(/\d+/, upvotes)); - votes.find(".downvotes").text(votes.find(".downvotes").text().replace(/\d+/, downvotes)); - } + updateVotes: function() { + var votes = $("#votes .votes"); + var notes = $("#notes-list").find(".note .vote"); + + // only update if there is a vote display + if (votes.size()) { + var upvotes = notes.filter(".upvote").size(); + var downvotes = notes.filter(".downvote").size(); + var votesCount = upvotes + downvotes; + var upvotesPercent = votesCount ? (100.0 / votesCount * upvotes) : 0; + var downvotesPercent = votesCount ? (100.0 - upvotesPercent) : 0; + + // change vote bar lengths + votes.find(".bar-success").css("width", upvotesPercent+"%"); + votes.find(".bar-danger").css("width", downvotesPercent+"%"); + // replace vote numbers + votes.find(".upvotes").text(votes.find(".upvotes").text().replace(/\d+/, upvotes)); + votes.find(".downvotes").text(votes.find(".downvotes").text().replace(/\d+/, downvotes)); } + } }; -- cgit v1.2.1 From 918dc873768359cbb7de5e83bc900fb0dacce938 Mon Sep 17 00:00:00 2001 From: Riyad Preukschas Date: Thu, 22 Nov 2012 00:42:55 +0100 Subject: Move code for appending a discussion note to notes JS --- app/assets/javascripts/notes.js | 14 ++++++++++++++ app/views/notes/_create_discussion_note.js.haml | 14 +++----------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/app/assets/javascripts/notes.js b/app/assets/javascripts/notes.js index 7f4bd330839..fec91c1fdb5 100644 --- a/app/assets/javascripts/notes.js +++ b/app/assets/javascripts/notes.js @@ -377,6 +377,20 @@ var NoteList = { this.updateVotes(); }, + appendNewDiscussionNote: function(discussionId, diffRowHtml, noteHtml) { + // is this the first note of discussion? + var row = $("form[rel='"+discussionId+"']").closest("tr"); + if (row.is(".js-temp-notes-holder")) { + // insert the note and the reply button after it + row.after(diffRowHtml); + // will be added again below + row.next().find(".note").remove(); + } + + // append new note to all matching discussions + $(".notes[rel='"+discussionId+"']").append(noteHtml); + }, + /** * Recalculates the votes and updates them (if they are displayed at all). * diff --git a/app/views/notes/_create_discussion_note.js.haml b/app/views/notes/_create_discussion_note.js.haml index 968ef0cfbee..91ba8593d45 100644 --- a/app/views/notes/_create_discussion_note.js.haml +++ b/app/views/notes/_create_discussion_note.js.haml @@ -1,13 +1,5 @@ - if note.valid? :plain - // is this the first note of discussion? - var row = $("form[rel='#{note.discussion_id}']").closest("tr"); - if (row.is(".js-temp-notes-holder")) { - // insert the note and the reply button after it - row.after("#{escape_javascript(render "notes/diff_notes_with_reply", notes: [note])}"); - // will be added again below - row.next().find(".note").remove(); - } - - // append new note to all discussions - $(".notes[rel='#{note.discussion_id}']").append("#{escape_javascript(render "notes/note", note: note)}"); + NoteList.appendNewDiscussionNote("#{note.discussion_id}", + "#{escape_javascript(render "notes/diff_notes_with_reply", notes: [note])}", + "#{escape_javascript(render "notes/note", note: note)}"); -- cgit v1.2.1 From 5d3fb35cd149288ddbab94ffa903c5977ca3da76 Mon Sep 17 00:00:00 2001 From: Riyad Preukschas Date: Thu, 22 Nov 2012 02:08:53 +0100 Subject: Rename JS behaviors --- app/assets/javascripts/behaviors/details_behavior.coffee | 5 +++++ app/assets/javascripts/behaviors/toggler_behavior.coffee | 5 +++++ app/assets/javascripts/behaviours/details_behavior.coffee | 5 ----- app/assets/javascripts/behaviours/toggler_behaviour.coffee | 5 ----- 4 files changed, 10 insertions(+), 10 deletions(-) create mode 100644 app/assets/javascripts/behaviors/details_behavior.coffee create mode 100644 app/assets/javascripts/behaviors/toggler_behavior.coffee delete mode 100644 app/assets/javascripts/behaviours/details_behavior.coffee delete mode 100644 app/assets/javascripts/behaviours/toggler_behaviour.coffee diff --git a/app/assets/javascripts/behaviors/details_behavior.coffee b/app/assets/javascripts/behaviors/details_behavior.coffee new file mode 100644 index 00000000000..7ad5c818946 --- /dev/null +++ b/app/assets/javascripts/behaviors/details_behavior.coffee @@ -0,0 +1,5 @@ +$ -> + $("body").on "click", ".js-details-target", -> + container = $(@).closest(".js-details-container") + + container.toggleClass("open") diff --git a/app/assets/javascripts/behaviors/toggler_behavior.coffee b/app/assets/javascripts/behaviors/toggler_behavior.coffee new file mode 100644 index 00000000000..3fefbf8e121 --- /dev/null +++ b/app/assets/javascripts/behaviors/toggler_behavior.coffee @@ -0,0 +1,5 @@ +$ -> + $("body").on "click", ".js-toggler-target", -> + container = $(@).closest(".js-toggler-container") + + container.toggleClass("on") diff --git a/app/assets/javascripts/behaviours/details_behavior.coffee b/app/assets/javascripts/behaviours/details_behavior.coffee deleted file mode 100644 index f75284d9cf6..00000000000 --- a/app/assets/javascripts/behaviours/details_behavior.coffee +++ /dev/null @@ -1,5 +0,0 @@ -$ -> - $("body").on "click", ".js-details-target", -> - container = $(@).closest ".js-details-container" - - container.toggleClass "open" diff --git a/app/assets/javascripts/behaviours/toggler_behaviour.coffee b/app/assets/javascripts/behaviours/toggler_behaviour.coffee deleted file mode 100644 index 76f200d4667..00000000000 --- a/app/assets/javascripts/behaviours/toggler_behaviour.coffee +++ /dev/null @@ -1,5 +0,0 @@ -$ -> - $("body").on "click", ".js-toggler-target", -> - container = $(@).closest ".js-toggler-container" - - container.toggleClass "on" -- cgit v1.2.1 From 140652e9b019addaf7022e18b6816ecb36eee80c Mon Sep 17 00:00:00 2001 From: Riyad Preukschas Date: Thu, 22 Nov 2012 02:56:42 +0100 Subject: Fix common form and note preview --- app/assets/javascripts/notes.js | 141 +++++++++++++----------- app/assets/stylesheets/behaviors.scss | 4 +- app/assets/stylesheets/sections/notes.scss | 24 ++-- app/views/notes/_common_form.html.haml | 40 ++++--- app/views/notes/_create_common_note.js.haml | 11 +- app/views/notes/_create_discussion_note.js.haml | 4 +- app/views/notes/_discussion_note_form.html.haml | 2 +- app/views/notes/_notes_with_form.html.haml | 3 +- 8 files changed, 122 insertions(+), 107 deletions(-) diff --git a/app/assets/javascripts/notes.js b/app/assets/javascripts/notes.js index fec91c1fdb5..3952ee292c3 100644 --- a/app/assets/javascripts/notes.js +++ b/app/assets/javascripts/notes.js @@ -10,24 +10,25 @@ var NoteList = { reversed: false, init: function(tid, tt, path) { - this.notes_path = path + ".js"; - this.target_id = tid; - this.target_type = tt; - this.reversed = $("#notes-list").is(".reversed"); - this.target_params = "target_type=" + this.target_type + "&target_id=" + this.target_id; - - if(this.reversed) { - var textarea = $(".note-text"); - $('.note_advanced_opts').hide(); + NoteList.notes_path = path + ".js"; + NoteList.target_id = tid; + NoteList.target_type = tt; + NoteList.reversed = $("#notes-list").is(".reversed"); + NoteList.target_params = "target_type=" + NoteList.target_type + "&target_id=" + NoteList.target_id; + + if(NoteList.reversed) { + var form = $("#new_note"); + form.find(".buttons, .note_advanced_opts").hide(); + var textarea = form.find(".js-note-text"); textarea.css("height", "40px"); textarea.on("focus", function(){ - $(this).css("height", "80px"); - $('.note_advanced_opts').show(); + textarea.css("height", "80px"); + form.find(".buttons, .note_advanced_opts").show(); }); } // get initial set of notes - this.getContent(); + NoteList.getContent(); disableButtonIfEmptyField(".js-note-text", ".js-comment-button"); @@ -37,34 +38,21 @@ var NoteList = { $(".file_name").text(filename); }); - // Setup note preview - $(document).on('click', '#preview-link', function(e) { - $('#preview-note').text('Loading...'); - - $(this).text($(this).text() === "Edit" ? "Preview" : "Edit"); - - var note_text = $('#note_note').val(); - - if(note_text.trim().length === 0) { - $('#preview-note').text('Nothing to preview.'); - } else { - $.post($(this).attr('href'), {note: note_text}).success(function(data) { - $('#preview-note').html(data); - }); - } - - $('#preview-note, #note_note').toggle(); - });+ - + // add a new diff note $(document).on("click", ".js-add-diff-note-button", NoteList.addDiffNote); - // reply to diff notes + // reply to diff/discussion notes $(document).on("click", ".js-discussion-reply-button", NoteList.replyToDiscussionNote); + // setup note preview + $(document).on("click", + ".js-note-preview-button", + NoteList.previewNote); + // hide diff note form $(document).on("click", ".js-close-discussion-note-form", @@ -83,8 +71,12 @@ var NoteList = { // clean up previews for forms $(document).on("ajax:complete", ".note-form-holder", function(){ - $(this).find('#preview-note').hide(); - $(this).find('#note_note').show(); + //$(this).find('.js-note-preview-button').text('Preview'); + //$(this).find('.js-note-preview').hide(); + + $(this).find('.error').remove(); + $(this).find('.js-note-text').val(""); + $(this).show(); }); }, @@ -123,6 +115,31 @@ var NoteList = { e.preventDefault(); }, + /** + * Shows the note preview. + * + * Lets the server render GFM into Html and displays it. + * + * Note: uses the Toggler behavior to toggle preview/edit views/buttons + */ + previewNote: function(e) { + var form = $(this).closest("form"); + var preview = form.find('.js-note-preview'); + var note_text = form.find('.js-note-text').val(); + + if(note_text.trim().length === 0) { + preview.text('Nothing to preview.'); + } else if($(this).data('url')) { + preview.text('Loading...'); + $.post($(this).data('url'), {note: note_text}) + .success(function(previewData) { + preview.html(previewData); + }); + } + + e.preventDefault(); + }, + /** * Called in response to deleting a note on a diff line. * @@ -233,8 +250,8 @@ var NoteList = { */ getContent: function() { $.ajax({ - url: this.notes_path, - data: this.target_params, + url: NoteList.notes_path, + data: NoteList.target_params, complete: function(){ $('.notes-status').removeClass("loading")}, beforeSend: function() { $('.notes-status').addClass("loading") }, dataType: "script" @@ -246,23 +263,23 @@ var NoteList = { * Replaces the content of #notes-list with the given html. */ setContent: function(newNoteIds, html) { - this.top_id = newNoteIds.first(); - this.bottom_id = newNoteIds.last(); + NoteList.top_id = newNoteIds.first(); + NoteList.bottom_id = newNoteIds.last(); $("#notes-list").html(html); - if (this.reversed) { + if (NoteList.reversed) { // init infinite scrolling - this.initLoadMore(); + NoteList.initLoadMore(); // init getting new notes - this.initRefreshNew(); + NoteList.initRefreshNew(); } }, /** * Handle loading more notes when scrolling to the bottom of the page. - * The id of the last note in the list is in this.bottom_id. + * The id of the last note in the list is in NoteList.bottom_id. * * Set up refreshing only new notes after all notes have been loaded. */ @@ -292,8 +309,8 @@ var NoteList = { // only load more notes if there are no "new" notes $('.loading').show(); $.ajax({ - url: this.notes_path, - data: this.target_params + "&loading_more=1&" + (this.reversed ? "before_id" : "after_id") + "=" + this.bottom_id, + url: NoteList.notes_path, + data: NoteList.target_params + "&loading_more=1&" + (NoteList.reversed ? "before_id" : "after_id") + "=" + NoteList.bottom_id, complete: function(){ $('.notes-status').removeClass("loading")}, beforeSend: function() { $('.notes-status').addClass("loading") }, dataType: "script" @@ -306,8 +323,8 @@ var NoteList = { */ appendMoreNotes: function(newNoteIds, html) { var lastNewNoteId = newNoteIds.last(); - if(lastNewNoteId != this.bottom_id) { - this.bottom_id = lastNewNoteId; + if(lastNewNoteId != NoteList.bottom_id) { + NoteList.bottom_id = lastNewNoteId; $("#notes-list").append(html); } }, @@ -315,17 +332,12 @@ var NoteList = { /** * Called in response to getMore(). * Disables loading more notes when scrolling to the bottom of the page. - * Initalizes refreshing new notes. */ finishedLoadingMore: function() { - this.loading_more_disabled = true; + NoteList.loading_more_disabled = true; - // from now on only get new notes - if (!this.reversed) { - this.initRefreshNew(); - } // make sure we are up to date - this.updateVotes(); + NoteList.updateVotes(); }, @@ -334,7 +346,7 @@ var NoteList = { * * New notes are all notes that are created after the site has been loaded. * The "old" notes are in #notes-list the "new" ones will be in #new-notes-list. - * The id of the last "old" note is in this.bottom_id. + * The id of the last "old" note is in NoteList.bottom_id. */ @@ -350,8 +362,8 @@ var NoteList = { */ getNew: function() { $.ajax({ - url: this.notes_path, - data: this.target_params + "&loading_new=1&after_id=" + (this.reversed ? this.top_id : this.bottom_id), + url: NoteList.notes_path, + data: NoteList.target_params + "&loading_new=1&after_id=" + (NoteList.reversed ? NoteList.top_id : NoteList.bottom_id), dataType: "script" }); }, @@ -362,21 +374,20 @@ var NoteList = { */ replaceNewNotes: function(newNoteIds, html) { $("#new-notes-list").html(html); - this.updateVotes(); + NoteList.updateVotes(); }, /** - * Adds a single note to #new-notes-list. + * Adds a single common note to #(new-)notes-list. */ appendNewNote: function(id, html) { - if (this.reversed) { - $("#notes-list").prepend(html); - } else { - $("#notes-list").append(html); - } - this.updateVotes(); + $("#notes-list").append(html); + NoteList.updateVotes(); }, + /** + * Adds a single discussion note to #(new-)notes-list. + */ appendNewDiscussionNote: function(discussionId, diffRowHtml, noteHtml) { // is this the first note of discussion? var row = $("form[rel='"+discussionId+"']").closest("tr"); @@ -401,7 +412,7 @@ var NoteList = { */ updateVotes: function() { var votes = $("#votes .votes"); - var notes = $("#notes-list").find(".note .vote"); + var notes = $("#notes-list .note .vote"); // only update if there is a vote display if (votes.size()) { diff --git a/app/assets/stylesheets/behaviors.scss b/app/assets/stylesheets/behaviors.scss index 20854e7ee22..3fdc20485f2 100644 --- a/app/assets/stylesheets/behaviors.scss +++ b/app/assets/stylesheets/behaviors.scss @@ -8,7 +8,7 @@ // Toggler //-------- -.js-toggler-container .turn-on { display: inline-block; } +.js-toggler-container .turn-on { display: inherit; } .js-toggler-container .turn-off { display: none; } .js-toggler-container.on .turn-on { display: none; } -.js-toggler-container.on .turn-off { display: inline-block; } +.js-toggler-container.on .turn-off { display: inherit; } diff --git a/app/assets/stylesheets/sections/notes.scss b/app/assets/stylesheets/sections/notes.scss index 2535d9f46ad..df7b16b145d 100644 --- a/app/assets/stylesheets/sections/notes.scss +++ b/app/assets/stylesheets/sections/notes.scss @@ -310,24 +310,26 @@ p.notify_controls span{ padding-right: 15px; } } - .note-text { + .note_preview { + margin: 2px; + border: 1px solid #ddd; + padding: 10px; + min-height: 60px; + background:#f5f5f5; + } + .note_text { border: 1px solid #aaa; - box-shadow:none; + box-shadow: none; } // TODO: end cleanup } // hide the new discussion note form template -.note-forms { +#note-forms { + .note-form-holder { + margin-top: 5px; + } .new_discussion_note { display: none; } } - -.preview_note { - margin: 2px; - border: 1px solid #ddd; - padding: 10px; - min-height: 60px; - background:#f5f5f5; -} diff --git a/app/views/notes/_common_form.html.haml b/app/views/notes/_common_form.html.haml index 7c25bf73296..3dfbe4b8a85 100644 --- a/app/views/notes/_common_form.html.haml +++ b/app/views/notes/_common_form.html.haml @@ -11,17 +11,32 @@ - @note.errors.full_messages.each do |msg| %div= msg - = f.text_area :note, size: 255, class: 'js-note-text js-gfm-input' - #preview-note.preview_note.hide - .hint - .right Comments are parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}. + .js-toggler-container + = f.text_area :note, size: 255, class: 'note_text turn-on js-note-text js-gfm-input' + .note_preview.js-note-preview.hide.turn-off + + .hint + .right Comments are parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}. .clearfix - .row.note_advanced_opts - .span3 + .buttons = f.submit 'Add Comment', class: "btn comment-btn grouped js-comment-button" - = link_to 'Preview', preview_project_notes_path(@project), class: 'btn grouped', id: 'preview-link' - .span4.notify_opts + %button.btn.grouped.js-note-preview-button.js-toggler-target.turn-on{ data: {url: preview_project_notes_path(@project)} } + Preview + %button.btn.grouped.js-note-preview-button.js-toggler-target.turn-off + Edit + + .note_advanced_opts + .attachments.right + %h6.left Attachment: + %span.file_name File name... + + .input.input_file + %a.file_upload.btn.small Upload File + = f.file_field :attachment, class: "input-file" + %span.hint Any file less than 10 MB + + .notify_opts.right %h6.left Notify via email: = label_tag :notify do = check_box_tag :notify, 1, @note.noteable_type != "Commit" @@ -31,11 +46,4 @@ = label_tag :notify_author do = check_box_tag :notify_author, 1 , @note.noteable_type == "Commit" %span Commit author - .span5.attachments - %h6.left Attachment: - %span.file_name File name... - - .input.input_file - %a.file_upload.btn.small Upload File - = f.file_field :attachment, class: "input-file" - %span.hint Any file less than 10 MB + .clearfix diff --git a/app/views/notes/_create_common_note.js.haml b/app/views/notes/_create_common_note.js.haml index 217c908064a..57c768b8088 100644 --- a/app/views/notes/_create_common_note.js.haml +++ b/app/views/notes/_create_common_note.js.haml @@ -1,13 +1,6 @@ - if note.valid? - :plain - $(".note-form-holder .error").remove(); - $('.note-form-holder textarea').val(""); - $('.note-form-holder #preview-link').text('Preview'); - $('.note-form-holder #preview-note').hide(); - $('.note-form-holder').show(); NoteList.appendNewNote(#{note.id}, "#{escape_javascript(render "notes/note", note: note)}"); - else - :plain - $(".note-form-holder").replaceWith("#{escape_javascript(render 'notes/common_form')}"); - GitLab.GfmAutoComplete.setup(); + $(".note-form-holder").replaceWith("#{escape_javascript(render 'notes/common_form')}"); + GitLab.GfmAutoComplete.setup(); diff --git a/app/views/notes/_create_discussion_note.js.haml b/app/views/notes/_create_discussion_note.js.haml index 91ba8593d45..3a6c3dad657 100644 --- a/app/views/notes/_create_discussion_note.js.haml +++ b/app/views/notes/_create_discussion_note.js.haml @@ -1,5 +1,5 @@ - if note.valid? :plain NoteList.appendNewDiscussionNote("#{note.discussion_id}", - "#{escape_javascript(render "notes/diff_notes_with_reply", notes: [note])}", - "#{escape_javascript(render "notes/note", note: note)}"); + "#{escape_javascript(render "notes/diff_notes_with_reply", notes: [note])}", + "#{escape_javascript(render "notes/note", note: note)}"); diff --git a/app/views/notes/_discussion_note_form.html.haml b/app/views/notes/_discussion_note_form.html.haml index 045bfdbf114..85b9a35e114 100644 --- a/app/views/notes/_discussion_note_form.html.haml +++ b/app/views/notes/_discussion_note_form.html.haml @@ -10,7 +10,7 @@ - @note.errors.full_messages.each do |msg| %div= msg - = f.text_area :note, size: 255, class: 'js-note-text js-gfm-input' + = f.text_area :note, size: 255, class: 'note_text js-note-text js-gfm-input' .note_actions .buttons = f.submit 'Add Comment', class: "btn comment-btn js-comment-button" diff --git a/app/views/notes/_notes_with_form.html.haml b/app/views/notes/_notes_with_form.html.haml index 3e3918412bb..117556d627b 100644 --- a/app/views/notes/_notes_with_form.html.haml +++ b/app/views/notes/_notes_with_form.html.haml @@ -1,7 +1,8 @@ %ul#notes-list.notes +.notes-status - if can? current_user, :write_note, @project - .note-forms.js-note-forms + #note-forms.js-note-forms = render "notes/common_form" = render "notes/discussion_note_form" -- cgit v1.2.1 From c4a7824a8c6487b24379f7f85c26f182bbc1dee9 Mon Sep 17 00:00:00 2001 From: Riyad Preukschas Date: Thu, 22 Nov 2012 02:57:22 +0100 Subject: Fix wall notes --- app/assets/javascripts/notes.js | 20 ++++++++++++++++++-- app/controllers/notes_controller.rb | 3 ++- app/helpers/notes_helper.rb | 3 ++- app/models/note.rb | 4 ++++ app/views/notes/_create_common_note.js.haml | 3 +++ 5 files changed, 29 insertions(+), 4 deletions(-) diff --git a/app/assets/javascripts/notes.js b/app/assets/javascripts/notes.js index 3952ee292c3..da356b2ef04 100644 --- a/app/assets/javascripts/notes.js +++ b/app/assets/javascripts/notes.js @@ -267,6 +267,7 @@ var NoteList = { NoteList.bottom_id = newNoteIds.last(); $("#notes-list").html(html); + // for the wall if (NoteList.reversed) { // init infinite scrolling NoteList.initLoadMore(); @@ -352,6 +353,8 @@ var NoteList = { /** * Initializes getting new notes every n seconds. + * + * Note: only used on wall. */ initRefreshNew: function() { setInterval("NoteList.getNew()", 10000); @@ -359,6 +362,8 @@ var NoteList = { /** * Gets the new set of notes. + * + * Note: only used on wall. */ getNew: function() { $.ajax({ @@ -371,6 +376,8 @@ var NoteList = { /** * Called in response to getNew(). * Replaces the content of #new-notes-list with the given html. + * + * Note: only used on wall. */ replaceNewNotes: function(newNoteIds, html) { $("#new-notes-list").html(html); @@ -378,7 +385,7 @@ var NoteList = { }, /** - * Adds a single common note to #(new-)notes-list. + * Adds a single common note to #notes-list. */ appendNewNote: function(id, html) { $("#notes-list").append(html); @@ -386,7 +393,7 @@ var NoteList = { }, /** - * Adds a single discussion note to #(new-)notes-list. + * Adds a single discussion note to #notes-list. */ appendNewDiscussionNote: function(discussionId, diffRowHtml, noteHtml) { // is this the first note of discussion? @@ -402,6 +409,15 @@ var NoteList = { $(".notes[rel='"+discussionId+"']").append(noteHtml); }, + /** + * Adds a single wall note to #new-notes-list. + * + * Note: only used on wall. + */ + appendNewWallNote: function(id, html) { + $("#new-notes-list").prepend(html); + }, + /** * Recalculates the votes and updates them (if they are displayed at all). * diff --git a/app/controllers/notes_controller.rb b/app/controllers/notes_controller.rb index e04a61b2905..000c7bbb641 100644 --- a/app/controllers/notes_controller.rb +++ b/app/controllers/notes_controller.rb @@ -71,6 +71,7 @@ class NotesController < ProjectResourceController # Helps to distinguish e.g. commit notes in mr notes list def note_for_main_target?(note) - @target_type.camelize == note.noteable_type && !note.for_diff_line? + note.for_wall? || + (@target_type.camelize == note.noteable_type && !note.for_diff_line?) end end diff --git a/app/helpers/notes_helper.rb b/app/helpers/notes_helper.rb index e82537a336f..fd920e23c19 100644 --- a/app/helpers/notes_helper.rb +++ b/app/helpers/notes_helper.rb @@ -1,7 +1,8 @@ module NotesHelper # Helps to distinguish e.g. commit notes in mr notes list def note_for_main_target?(note) - @target_type.camelize == note.noteable_type && !note.for_diff_line? + note.for_wall? || + (@target_type.camelize == note.noteable_type && !note.for_diff_line?) end def note_target_fields diff --git a/app/models/note.rb b/app/models/note.rb index 48916951e3b..0027c57b63b 100644 --- a/app/models/note.rb +++ b/app/models/note.rb @@ -115,6 +115,10 @@ class Note < ActiveRecord::Base for_merge_request? && for_diff_line? end + def for_wall? + noteable_type.blank? + end + # override to return commits, which are not active record def noteable if for_commit? diff --git a/app/views/notes/_create_common_note.js.haml b/app/views/notes/_create_common_note.js.haml index 57c768b8088..20bc07568a0 100644 --- a/app/views/notes/_create_common_note.js.haml +++ b/app/views/notes/_create_common_note.js.haml @@ -1,4 +1,7 @@ - if note.valid? + - if note.for_wall? + NoteList.appendNewWallNote(#{note.id}, "#{escape_javascript(render "notes/note", note: note)}"); + - else NoteList.appendNewNote(#{note.id}, "#{escape_javascript(render "notes/note", note: note)}"); - else -- cgit v1.2.1 From fbd345ea20eaabc58fe84a2cdf3ba960f3a10c24 Mon Sep 17 00:00:00 2001 From: Riyad Preukschas Date: Thu, 22 Nov 2012 03:20:41 +0100 Subject: Make attachments more obvious --- app/assets/stylesheets/sections/notes.scss | 18 +++++++++++++++--- app/views/notes/_note.html.haml | 9 +++++---- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/app/assets/stylesheets/sections/notes.scss b/app/assets/stylesheets/sections/notes.scss index df7b16b145d..e8bf3d631cc 100644 --- a/app/assets/stylesheets/sections/notes.scss +++ b/app/assets/stylesheets/sections/notes.scss @@ -76,10 +76,22 @@ ul.notes { p { color: $style_color; } .avatar { - margin-top:3px; + margin-top: 3px; + } + .attachment { + font-size: 16px; + margin-top: -20px; + + .icon-attachment { + @extend .icon-paper-clip; + font-size: 24px; + position: relative; + text-align: right; + top: 6px; + } } .note-body { - margin-left:45px; + margin-left: 45px; padding-top: 5px; } .note-header { @@ -187,7 +199,7 @@ p.notify_controls span{ // TODO: end cleaup /** - * add line note button on the side of diffs + * line note button on the side of diffs */ .diff_file tr.line_holder { .add-diff-note { diff --git a/app/views/notes/_note.html.haml b/app/views/notes/_note.html.haml index c0c0b725146..980300c4657 100644 --- a/app/views/notes/_note.html.haml +++ b/app/views/notes/_note.html.haml @@ -27,8 +27,9 @@ .note-body = preserve do = markdown(note.note) - - if note.attachment.url - .right - %div.file - = link_to note.attachment_identifier, note.attachment.url, target: "_blank" + - if note.attachment.url + .attachment.right + = link_to note.attachment.url, target: "_blank" do + %i.icon-attachment + = note.attachment_identifier .clear -- cgit v1.2.1 From 6fc10fa2564538bb892090759fdb05604b0e5567 Mon Sep 17 00:00:00 2001 From: Riyad Preukschas Date: Sun, 2 Dec 2012 20:47:09 +0100 Subject: Unify forms for discussions and main target. Allows previews and uploads in all forms. Also fixes #1730 --- app/assets/javascripts/notes.js | 121 +++++++++++++++------ app/assets/stylesheets/sections/notes.scss | 96 +++++++--------- app/views/notes/_common_form.html.haml | 96 ++++++++-------- app/views/notes/_create_common_note.js.haml | 3 +- app/views/notes/_discussion_note_form.html.haml | 28 ----- app/views/notes/_notes_with_form.html.haml | 5 +- .../notes/_reversed_notes_with_form.html.haml | 1 + 7 files changed, 178 insertions(+), 172 deletions(-) delete mode 100644 app/views/notes/_discussion_note_form.html.haml diff --git a/app/assets/javascripts/notes.js b/app/assets/javascripts/notes.js index da356b2ef04..c9137c887b9 100644 --- a/app/assets/javascripts/notes.js +++ b/app/assets/javascripts/notes.js @@ -16,22 +16,22 @@ var NoteList = { NoteList.reversed = $("#notes-list").is(".reversed"); NoteList.target_params = "target_type=" + NoteList.target_type + "&target_id=" + NoteList.target_id; + NoteList.setupMainTargetNoteForm(); + if(NoteList.reversed) { - var form = $("#new_note"); - form.find(".buttons, .note_advanced_opts").hide(); + var form = $(".js-main-target-form"); + form.find(".buttons, .note_options").hide(); var textarea = form.find(".js-note-text"); textarea.css("height", "40px"); textarea.on("focus", function(){ textarea.css("height", "80px"); - form.find(".buttons, .note_advanced_opts").show(); + form.find(".buttons, .note_options").show(); }); } // get initial set of notes NoteList.getContent(); - disableButtonIfEmptyField(".js-note-text", ".js-comment-button"); - $("#note_attachment").change(function(e){ var val = $('.input-file').val(); var filename = val.replace(/^.*[\\\/]/, ''); @@ -70,10 +70,7 @@ var NoteList = { NoteList.removeNote); // clean up previews for forms - $(document).on("ajax:complete", ".note-form-holder", function(){ - //$(this).find('.js-note-preview-button').text('Preview'); - //$(this).find('.js-note-preview').hide(); - + $(document).on("ajax:complete", ".js-main-target-form", function(){ $(this).find('.error').remove(); $(this).find('.js-note-text').val(""); $(this).show(); @@ -93,8 +90,10 @@ var NoteList = { * Sets up the form and shows it. */ addDiffNote: function(e) { + e.preventDefault(); + // find the form - var form = $(".js-note-forms .js-discussion-note-form"); + var form = $(".js-new-note-form"); var row = $(this).closest("tr"); var nextRow = row.next(); @@ -111,8 +110,6 @@ var NoteList = { // show the form NoteList.setupDiscussionNoteForm($(this), row.next().find("form")); } - - e.preventDefault(); }, /** @@ -123,21 +120,23 @@ var NoteList = { * Note: uses the Toggler behavior to toggle preview/edit views/buttons */ previewNote: function(e) { + e.preventDefault(); + var form = $(this).closest("form"); var preview = form.find('.js-note-preview'); - var note_text = form.find('.js-note-text').val(); + var noteText = form.find('.js-note-text').val(); + + console.log("preview", noteText); - if(note_text.trim().length === 0) { + if(noteText.trim().length === 0) { preview.text('Nothing to preview.'); - } else if($(this).data('url')) { + } else { preview.text('Loading...'); - $.post($(this).data('url'), {note: note_text}) + $.post($(this).data('url'), {note: noteText}) .success(function(previewData) { preview.html(previewData); }); } - - e.preventDefault(); }, /** @@ -168,6 +167,8 @@ var NoteList = { * Removes the form and if necessary it's temporary row. */ removeDiscussionNoteForm: function(e) { + e.preventDefault(); + var form = $(this).closest("form"); var row = form.closest("tr"); @@ -181,8 +182,6 @@ var NoteList = { // only remove the form form.remove(); } - - e.preventDefault(); }, /** @@ -202,7 +201,7 @@ var NoteList = { */ replyToDiscussionNote: function() { // find the form - var form = $(".js-note-forms .js-discussion-note-form"); + var form = $(".js-new-note-form"); // hide reply button $(this).hide(); @@ -213,27 +212,83 @@ var NoteList = { NoteList.setupDiscussionNoteForm($(this), $(this).next("form")); }, + + /** + * Helper for inserting and setting up note forms. + */ + + /** - * Shows the diff line form and does some setup. + * Shows the diff/discussion form and does some setup on it. * * Sets some hidden fields in the form. * - * Note: "this" must have the "discussionId", "lineCode", "noteableType" and - * "noteableId" data attributes set. + * Note: dataHolder must have the "discussionId", "lineCode", "noteableType" + * and "noteableId" data attributes set. */ - setupDiscussionNoteForm: function(data_holder, form) { + setupDiscussionNoteForm: function(dataHolder, form) { // setup note target - form.attr("rel", data_holder.data("discussionId")); - form.find("#note_line_code").val(data_holder.data("lineCode")); - form.find("#note_noteable_type").val(data_holder.data("noteableType")); - form.find("#note_noteable_id").val(data_holder.data("noteableId")); + form.attr("rel", dataHolder.data("discussionId")); + form.find("#note_line_code").val(dataHolder.data("lineCode")); + form.find("#note_noteable_type").val(dataHolder.data("noteableType")); + form.find("#note_noteable_id").val(dataHolder.data("noteableId")); - // setup interaction - disableButtonIfEmptyField(form.find(".js-note-text"), form.find(".js-comment-button")); - GitLab.GfmAutoComplete.setup(); + NoteList.setupNoteForm(form); - // cleanup after successfully creating a diff note + // cleanup after successfully creating a diff/discussion note form.on("ajax:success", NoteList.removeDiscussionNoteForm); + }, + + /** + * Shows the main form and does some setup on it. + * + * Sets some hidden fields in the form. + */ + setupMainTargetNoteForm: function() { + // find the form + var form = $(".js-new-note-form"); + // insert the form after the button + form.clone().replaceAll($(".js-main-target-form")); + + form = form.prev("form"); + + // show the form + NoteList.setupNoteForm(form); + + // fix classes + form.removeClass("js-new-note-form"); + form.addClass("js-main-target-form"); + + // remove unnecessary fields and buttons + form.find("#note_line_code").remove(); + form.find(".js-close-discussion-note-form").remove(); + }, + + /** + * General note form setup. + * + * * deactivates the submit button when text is empty + * * hides the preview button when text is empty + * * setup GFM auto complete + * * show the form + */ + setupNoteForm: function(form) { + disableButtonIfEmptyField(form.find(".js-note-text"), form.find(".js-comment-button")); + + // setup preview buttons + $(".js-note-edit-button, .js-note-preview-button").tooltip({ placement: 'left' }); + + previewButton = $(".js-note-preview-button"); + previewButton.hide(); + form.find(".js-note-text").on("input", function() { + if ($(this).val().trim() !== "") { + previewButton.fadeIn(); + } else { + previewButton.fadeOut(); + } + }); + + GitLab.GfmAutoComplete.setup(); form.show(); }, diff --git a/app/assets/stylesheets/sections/notes.scss b/app/assets/stylesheets/sections/notes.scss index e8bf3d631cc..6a2f784e72c 100644 --- a/app/assets/stylesheets/sections/notes.scss +++ b/app/assets/stylesheets/sections/notes.scss @@ -239,46 +239,51 @@ p.notify_controls span{ .reply-btn { @extend .save-btn; } -.new_discussion_note { - // hide it by default +.diff_file, +.discussion { + .new_note { + margin: 8px 5px 8px 0; + } +} +.new_note { display: none; - margin: 8px 5px 8px 0; - // TODO: start cleanup - .note_actions { - margin:0; - padding-top: 10px; + .buttons { + float: left; + margin-top: 8px; + } + .note_options { + h6 { + line-height: 32px; + padding-right: 15px; + } + } + .note_text_and_preview { + // makes the "absolute" position for links relative to this + position: relative; - .buttons { - float:left; - width:300px; + // preview/edit buttons + > a { + font-size: 24px; + padding: 4px; + position: absolute; + right: 0; } - .options { - .labels { - float:left; - padding-left:10px; - label { - padding: 6px 0; - margin: 0; - width:120px; - } - } + .note_preview { + background: #f5f5f5; + border: 1px solid #ddd; + @include border-radius(4px); + min-height: 80px; + padding: 4px 6px; + } + .note_text { + font-size: 14px; + height: 80px; + width: 98.6%; } - } - // TODO: end cleanup -} -.new_note { - textarea { - height:80px; - width:99%; - font-size:14px; } // TODO: start cleanup - .attach_holder { - display:none; - } - .attachments { position: relative; width: 350px; @@ -316,32 +321,5 @@ p.notify_controls span{ padding:0; margin: 0; } - .note_advanced_opts { - h6 { - line-height: 32px; - padding-right: 15px; - } - } - .note_preview { - margin: 2px; - border: 1px solid #ddd; - padding: 10px; - min-height: 60px; - background:#f5f5f5; - } - .note_text { - border: 1px solid #aaa; - box-shadow: none; - } // TODO: end cleanup } - -// hide the new discussion note form template -#note-forms { - .note-form-holder { - margin-top: 5px; - } - .new_discussion_note { - display: none; - } -} diff --git a/app/views/notes/_common_form.html.haml b/app/views/notes/_common_form.html.haml index 3dfbe4b8a85..9d600447296 100644 --- a/app/views/notes/_common_form.html.haml +++ b/app/views/notes/_common_form.html.haml @@ -1,49 +1,49 @@ -.note-form-holder - = form_for [@project, @note], remote: "true", multipart: true do |f| - - = note_target_fields - = f.hidden_field :noteable_id - = f.hidden_field :noteable_type - - %h3.page_title Leave a comment - -if @note.errors.any? - .alert-message.block-message.error - - @note.errors.full_messages.each do |msg| - %div= msg - - .js-toggler-container - = f.text_area :note, size: 255, class: 'note_text turn-on js-note-text js-gfm-input' - .note_preview.js-note-preview.hide.turn-off - - .hint - .right Comments are parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}. - .clearfix - - .buttons - = f.submit 'Add Comment', class: "btn comment-btn grouped js-comment-button" - %button.btn.grouped.js-note-preview-button.js-toggler-target.turn-on{ data: {url: preview_project_notes_path(@project)} } - Preview - %button.btn.grouped.js-note-preview-button.js-toggler-target.turn-off - Edit - - .note_advanced_opts - .attachments.right - %h6.left Attachment: - %span.file_name File name... - - .input.input_file - %a.file_upload.btn.small Upload File - = f.file_field :attachment, class: "input-file" - %span.hint Any file less than 10 MB - - .notify_opts.right - %h6.left Notify via email: - = label_tag :notify do - = check_box_tag :notify, 1, @note.noteable_type != "Commit" - %span Project team - - - if @note.notify_only_author?(current_user) - = label_tag :notify_author do - = check_box_tag :notify_author, 1 , @note.noteable_type == "Commit" - %span Commit author += form_for [@project, @note], remote: true, html: { multipart: true, id: nil, class: "new_note js-new-note-form" } do |f| + + = note_target_fields + = f.hidden_field :line_code + = f.hidden_field :noteable_id + = f.hidden_field :noteable_type + + - if @note.errors.any? + .alert-message.block-message.error + - @note.errors.full_messages.each do |msg| + %div= msg + + .note_text_and_preview.js-toggler-container + %a.js-note-preview-button.js-toggler-target.turn-on{ href: "javascript:;", data: {title: "Preview", url: preview_project_notes_path(@project)} } + %i.icon-eye-open + %a.js-note-edit-button.js-toggler-target.turn-off{ href: "javascript:;", data: {title: "Edit"} } + %i.icon-edit + + = f.text_area :note, size: 255, class: 'note_text js-note-text js-gfm-input turn-on' + .note_preview.js-note-preview.turn-off + + .buttons + = f.submit 'Add Comment', class: "btn comment-btn grouped js-comment-button" + %a.btn.grouped.js-close-discussion-note-form Cancel + .hint + .right Comments are parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}. + .clearfix + + .note_options + .attachments.right + %h6.left Attachment: + %span.file_name File name... + + .input.input_file + %a.file_upload.btn.small Upload File + = f.file_field :attachment, class: "input-file" + %span.hint Any file less than 10 MB + + .notify_opts.right + %h6.left Notify via email: + = label_tag :notify do + = check_box_tag :notify, 1, !@note.for_commit? + %span Project team + + - if @note.notify_only_author?(current_user) + = label_tag :notify_author do + = check_box_tag :notify_author, 1 , !@note.for_commit? + %span Commit author .clearfix diff --git a/app/views/notes/_create_common_note.js.haml b/app/views/notes/_create_common_note.js.haml index 20bc07568a0..7ea8c4cd8c7 100644 --- a/app/views/notes/_create_common_note.js.haml +++ b/app/views/notes/_create_common_note.js.haml @@ -5,5 +5,6 @@ NoteList.appendNewNote(#{note.id}, "#{escape_javascript(render "notes/note", note: note)}"); - else - $(".note-form-holder").replaceWith("#{escape_javascript(render 'notes/common_form')}"); + -# TODO: insert form correctly + $(".js-main-target-note").replaceWith("#{escape_javascript(render 'notes/common_form')}"); GitLab.GfmAutoComplete.setup(); diff --git a/app/views/notes/_discussion_note_form.html.haml b/app/views/notes/_discussion_note_form.html.haml deleted file mode 100644 index 85b9a35e114..00000000000 --- a/app/views/notes/_discussion_note_form.html.haml +++ /dev/null @@ -1,28 +0,0 @@ -= form_for [@project, @note], remote: true, html: { multipart: true, class: "new_note new_discussion_note js-discussion-note-form" } do |f| - - = note_target_fields - = f.hidden_field :line_code - = f.hidden_field :noteable_id - = f.hidden_field :noteable_type - - -if @note.errors.any? - .alert-message.block-message.error - - @note.errors.full_messages.each do |msg| - %div= msg - - = f.text_area :note, size: 255, class: 'note_text js-note-text js-gfm-input' - .note_actions - .buttons - = f.submit 'Add Comment', class: "btn comment-btn js-comment-button" - %button.btn.js-close-discussion-note-form Cancel - .options - %h6.left Notify via email: - .labels - = label_tag :notify do - = check_box_tag :notify, 1, @note.noteable_type != "Commit" - %span Project team - - - if @note.notify_only_author?(current_user) - = label_tag :notify_author do - = check_box_tag :notify_author, 1 , @note.noteable_type == "Commit" - %span Commit author diff --git a/app/views/notes/_notes_with_form.html.haml b/app/views/notes/_notes_with_form.html.haml index 117556d627b..2511cbe52c2 100644 --- a/app/views/notes/_notes_with_form.html.haml +++ b/app/views/notes/_notes_with_form.html.haml @@ -1,10 +1,9 @@ %ul#notes-list.notes .notes-status +.js-main-target-form - if can? current_user, :write_note, @project - #note-forms.js-note-forms - = render "notes/common_form" - = render "notes/discussion_note_form" + = render "notes/common_form" :javascript $(function(){ diff --git a/app/views/notes/_reversed_notes_with_form.html.haml b/app/views/notes/_reversed_notes_with_form.html.haml index 50fdad2ce1f..6a7f08f9b90 100644 --- a/app/views/notes/_reversed_notes_with_form.html.haml +++ b/app/views/notes/_reversed_notes_with_form.html.haml @@ -1,3 +1,4 @@ +.js-main-target-form - if can? current_user, :write_note, @project = render "notes/common_form" -- cgit v1.2.1 From c20af32ae4adb1ec891e32ea048ae06ef4c7bc5f Mon Sep 17 00:00:00 2001 From: Riyad Preukschas Date: Sun, 2 Dec 2012 23:14:56 +0100 Subject: Pull together and rename Notes partials --- app/views/notes/_common_form.html.haml | 49 ---------------------- app/views/notes/_create_common_note.js.haml | 10 ----- app/views/notes/_create_discussion_note.js.haml | 5 --- app/views/notes/_form.html.haml | 49 ++++++++++++++++++++++ app/views/notes/_notes_with_form.html.haml | 4 +- .../notes/_reversed_notes_with_form.html.haml | 4 +- app/views/notes/create.js.haml | 18 ++++++-- app/views/notes/index.js.haml | 13 +++--- 8 files changed, 73 insertions(+), 79 deletions(-) delete mode 100644 app/views/notes/_common_form.html.haml delete mode 100644 app/views/notes/_create_common_note.js.haml delete mode 100644 app/views/notes/_create_discussion_note.js.haml create mode 100644 app/views/notes/_form.html.haml diff --git a/app/views/notes/_common_form.html.haml b/app/views/notes/_common_form.html.haml deleted file mode 100644 index 9d600447296..00000000000 --- a/app/views/notes/_common_form.html.haml +++ /dev/null @@ -1,49 +0,0 @@ -= form_for [@project, @note], remote: true, html: { multipart: true, id: nil, class: "new_note js-new-note-form" } do |f| - - = note_target_fields - = f.hidden_field :line_code - = f.hidden_field :noteable_id - = f.hidden_field :noteable_type - - - if @note.errors.any? - .alert-message.block-message.error - - @note.errors.full_messages.each do |msg| - %div= msg - - .note_text_and_preview.js-toggler-container - %a.js-note-preview-button.js-toggler-target.turn-on{ href: "javascript:;", data: {title: "Preview", url: preview_project_notes_path(@project)} } - %i.icon-eye-open - %a.js-note-edit-button.js-toggler-target.turn-off{ href: "javascript:;", data: {title: "Edit"} } - %i.icon-edit - - = f.text_area :note, size: 255, class: 'note_text js-note-text js-gfm-input turn-on' - .note_preview.js-note-preview.turn-off - - .buttons - = f.submit 'Add Comment', class: "btn comment-btn grouped js-comment-button" - %a.btn.grouped.js-close-discussion-note-form Cancel - .hint - .right Comments are parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}. - .clearfix - - .note_options - .attachments.right - %h6.left Attachment: - %span.file_name File name... - - .input.input_file - %a.file_upload.btn.small Upload File - = f.file_field :attachment, class: "input-file" - %span.hint Any file less than 10 MB - - .notify_opts.right - %h6.left Notify via email: - = label_tag :notify do - = check_box_tag :notify, 1, !@note.for_commit? - %span Project team - - - if @note.notify_only_author?(current_user) - = label_tag :notify_author do - = check_box_tag :notify_author, 1 , !@note.for_commit? - %span Commit author - .clearfix diff --git a/app/views/notes/_create_common_note.js.haml b/app/views/notes/_create_common_note.js.haml deleted file mode 100644 index 7ea8c4cd8c7..00000000000 --- a/app/views/notes/_create_common_note.js.haml +++ /dev/null @@ -1,10 +0,0 @@ -- if note.valid? - - if note.for_wall? - NoteList.appendNewWallNote(#{note.id}, "#{escape_javascript(render "notes/note", note: note)}"); - - else - NoteList.appendNewNote(#{note.id}, "#{escape_javascript(render "notes/note", note: note)}"); - -- else - -# TODO: insert form correctly - $(".js-main-target-note").replaceWith("#{escape_javascript(render 'notes/common_form')}"); - GitLab.GfmAutoComplete.setup(); diff --git a/app/views/notes/_create_discussion_note.js.haml b/app/views/notes/_create_discussion_note.js.haml deleted file mode 100644 index 3a6c3dad657..00000000000 --- a/app/views/notes/_create_discussion_note.js.haml +++ /dev/null @@ -1,5 +0,0 @@ -- if note.valid? - :plain - NoteList.appendNewDiscussionNote("#{note.discussion_id}", - "#{escape_javascript(render "notes/diff_notes_with_reply", notes: [note])}", - "#{escape_javascript(render "notes/note", note: note)}"); diff --git a/app/views/notes/_form.html.haml b/app/views/notes/_form.html.haml new file mode 100644 index 00000000000..9d600447296 --- /dev/null +++ b/app/views/notes/_form.html.haml @@ -0,0 +1,49 @@ += form_for [@project, @note], remote: true, html: { multipart: true, id: nil, class: "new_note js-new-note-form" } do |f| + + = note_target_fields + = f.hidden_field :line_code + = f.hidden_field :noteable_id + = f.hidden_field :noteable_type + + - if @note.errors.any? + .alert-message.block-message.error + - @note.errors.full_messages.each do |msg| + %div= msg + + .note_text_and_preview.js-toggler-container + %a.js-note-preview-button.js-toggler-target.turn-on{ href: "javascript:;", data: {title: "Preview", url: preview_project_notes_path(@project)} } + %i.icon-eye-open + %a.js-note-edit-button.js-toggler-target.turn-off{ href: "javascript:;", data: {title: "Edit"} } + %i.icon-edit + + = f.text_area :note, size: 255, class: 'note_text js-note-text js-gfm-input turn-on' + .note_preview.js-note-preview.turn-off + + .buttons + = f.submit 'Add Comment', class: "btn comment-btn grouped js-comment-button" + %a.btn.grouped.js-close-discussion-note-form Cancel + .hint + .right Comments are parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}. + .clearfix + + .note_options + .attachments.right + %h6.left Attachment: + %span.file_name File name... + + .input.input_file + %a.file_upload.btn.small Upload File + = f.file_field :attachment, class: "input-file" + %span.hint Any file less than 10 MB + + .notify_opts.right + %h6.left Notify via email: + = label_tag :notify do + = check_box_tag :notify, 1, !@note.for_commit? + %span Project team + + - if @note.notify_only_author?(current_user) + = label_tag :notify_author do + = check_box_tag :notify_author, 1 , !@note.for_commit? + %span Commit author + .clearfix diff --git a/app/views/notes/_notes_with_form.html.haml b/app/views/notes/_notes_with_form.html.haml index 2511cbe52c2..2566edd81ad 100644 --- a/app/views/notes/_notes_with_form.html.haml +++ b/app/views/notes/_notes_with_form.html.haml @@ -1,9 +1,9 @@ %ul#notes-list.notes -.notes-status +.js-notes-busy .js-main-target-form - if can? current_user, :write_note, @project - = render "notes/common_form" + = render "notes/form" :javascript $(function(){ diff --git a/app/views/notes/_reversed_notes_with_form.html.haml b/app/views/notes/_reversed_notes_with_form.html.haml index 6a7f08f9b90..bb583b8c3b8 100644 --- a/app/views/notes/_reversed_notes_with_form.html.haml +++ b/app/views/notes/_reversed_notes_with_form.html.haml @@ -1,10 +1,10 @@ .js-main-target-form - if can? current_user, :write_note, @project - = render "notes/common_form" + = render "notes/form" %ul#new-notes-list.reversed.notes %ul#notes-list.reversed.notes -.notes-status +.notes-busy.js-notes-busy :javascript $(function(){ diff --git a/app/views/notes/create.js.haml b/app/views/notes/create.js.haml index 03aec54b018..6ffb0cdee0e 100644 --- a/app/views/notes/create.js.haml +++ b/app/views/notes/create.js.haml @@ -1,4 +1,16 @@ -- if note_for_main_target?(@note) - = render "create_common_note", note: @note +- if @note.valid? + var noteHtml = "#{escape_javascript(render "notes/note", note: @note)}"; + + - if note_for_main_target?(@note) + - if @note.for_wall? + NoteList.appendNewWallNote(#{@note.id}, noteHtml); + - else + NoteList.appendNewNote(#{@note.id}, noteHtml); + - else + var firstDiscussionNoteHtml = "#{escape_javascript(render "notes/diff_notes_with_reply", notes: [@note])}"; + NoteList.appendNewDiscussionNote("#{@note.discussion_id}", firstDiscussionNoteHtml, noteHtml); + - else - = render "create_discussion_note", note: @note + -# TODO: insert form correctly + $(".js-main-target-note").replaceWith("#{escape_javascript(render 'notes/common_form')}"); + GitLab.GfmAutoComplete.setup(); \ No newline at end of file diff --git a/app/views/notes/index.js.haml b/app/views/notes/index.js.haml index ae70dcad289..f0826100fbf 100644 --- a/app/views/notes/index.js.haml +++ b/app/views/notes/index.js.haml @@ -1,18 +1,15 @@ - unless @notes.blank? + var notesHtml = "#{escape_javascript(render 'notes/notes')}"; - new_note_ids = @notes.map(&:id) - if loading_more_notes? - :plain - NoteList.appendMoreNotes(#{new_note_ids}, "#{escape_javascript(render 'notes/notes')}"); + NoteList.appendMoreNotes(#{new_note_ids}, notesHtml); - elsif loading_new_notes? - :plain - NoteList.replaceNewNotes(#{new_note_ids}, "#{escape_javascript(render 'notes/notes')}"); + NoteList.replaceNewNotes(#{new_note_ids}, notesHtml); - else - :plain - NoteList.setContent(#{new_note_ids}, "#{escape_javascript(render 'notes/notes')}"); + NoteList.setContent(#{new_note_ids}, notesHtml); - else - if loading_more_notes? - :plain - NoteList.finishedLoadingMore(); + NoteList.finishedLoadingMore(); -- cgit v1.2.1 From c1ffee4e65601a42c5d40ec5f3ddddb51a93251f Mon Sep 17 00:00:00 2001 From: Riyad Preukschas Date: Mon, 3 Dec 2012 19:33:01 +0100 Subject: Fix dicussion headers --- app/views/notes/_discussion.html.haml | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/app/views/notes/_discussion.html.haml b/app/views/notes/_discussion.html.haml index 7e9d366e286..031f4477ce3 100644 --- a/app/views/notes/_discussion.html.haml +++ b/app/views/notes/_discussion.html.haml @@ -21,13 +21,12 @@ - else %cite.cgray started a discussion %div - - if discussion_notes.size > 1 - - last_note = discussion_notes.last - last updated by - = link_to last_note.author_name, project_team_member_path(@project, @project.team_member_by_id(last_note.author)), class: "note-author" - %span.discussion-last-update - = time_ago_in_words(last_note.updated_at) - ago + - last_note = discussion_notes.last + last updated by + = link_to last_note.author_name, project_team_member_path(@project, @project.team_member_by_id(last_note.author)), class: "note-author" + %span.discussion-last-update + = time_ago_in_words(last_note.updated_at) + ago .discussion-body - if note.for_diff_line? .content -- cgit v1.2.1 From 7978f8dd2b62baacb0d045b65282b758a76da118 Mon Sep 17 00:00:00 2001 From: Riyad Preukschas Date: Mon, 3 Dec 2012 20:35:09 +0100 Subject: Fix handling form errors. --- app/assets/javascripts/notes.js | 66 ++++++++++++++++++++++++++++------ app/views/notes/_form.html.haml | 5 --- app/views/notes/_form_errors.html.haml | 3 ++ app/views/notes/create.js.haml | 15 +++++--- 4 files changed, 68 insertions(+), 21 deletions(-) create mode 100644 app/views/notes/_form_errors.html.haml diff --git a/app/assets/javascripts/notes.js b/app/assets/javascripts/notes.js index c9137c887b9..8c4577bd1fc 100644 --- a/app/assets/javascripts/notes.js +++ b/app/assets/javascripts/notes.js @@ -69,12 +69,10 @@ var NoteList = { ".js-note-delete", NoteList.removeNote); - // clean up previews for forms - $(document).on("ajax:complete", ".js-main-target-form", function(){ - $(this).find('.error').remove(); - $(this).find('.js-note-text').val(""); - $(this).show(); - }); + // clean up previews for main target form + $(document).on("ajax:complete", + ".js-main-target-form", + NoteList.cleanupMainTargetForm); }, @@ -83,6 +81,26 @@ var NoteList = { */ + /** + * + */ + cleanupMainTargetForm: function(){ + var form = $(this); + + // remove validation errors + form.find(".js-errors").remove(); + + // reset text and preview + var previewContainer = form.find(".js-toggler-container.note_text_and_preview"); + if (previewContainer.is(".on")) { + previewContainer.removeClass("on"); + } + form.find(".js-note-text").val("").trigger("input"); + + // re-enable submit button + form.find(".js-comment-button").enable(); + }, + /** * Called when clicking on the "add a comment" button on the side of a diff line. * @@ -218,6 +236,27 @@ var NoteList = { */ + /** + * Called in response to creating a note failing validation. + * + * Adds the rendered errors to the respective form. + * If "discussionId" is null or undefined, the main target form is assumed. + */ + errorsOnForm: function(errorsHtml, discussionId) { + // find the form + if (discussionId) { + var form = $("form[rel='"+discussionId+"']"); + } else { + var form = $(".js-main-target-form"); + } + + form.find(".js-errors").remove(); + form.prepend(errorsHtml); + + form.find(".js-note-text").focus(); + }, + + /** * Shows the diff/discussion form and does some setup on it. * @@ -235,8 +274,6 @@ var NoteList = { NoteList.setupNoteForm(form); - // cleanup after successfully creating a diff/discussion note - form.on("ajax:success", NoteList.removeDiscussionNoteForm); }, /** @@ -449,19 +486,26 @@ var NoteList = { /** * Adds a single discussion note to #notes-list. + * + * Also removes the corresponding form. */ appendNewDiscussionNote: function(discussionId, diffRowHtml, noteHtml) { + var form = $("form[rel='"+discussionId+"']"); + var row = form.closest("tr"); + // is this the first note of discussion? - var row = $("form[rel='"+discussionId+"']").closest("tr"); if (row.is(".js-temp-notes-holder")) { - // insert the note and the reply button after it + // insert the note and the reply button after the temp row row.after(diffRowHtml); - // will be added again below + // remove the note (will be added again below) row.next().find(".note").remove(); } // append new note to all matching discussions $(".notes[rel='"+discussionId+"']").append(noteHtml); + + // cleanup after successfully creating a diff/discussion note + $.proxy(NoteList.removeDiscussionNoteForm, form).call(); }, /** diff --git a/app/views/notes/_form.html.haml b/app/views/notes/_form.html.haml index 9d600447296..f4a79b0b196 100644 --- a/app/views/notes/_form.html.haml +++ b/app/views/notes/_form.html.haml @@ -5,11 +5,6 @@ = f.hidden_field :noteable_id = f.hidden_field :noteable_type - - if @note.errors.any? - .alert-message.block-message.error - - @note.errors.full_messages.each do |msg| - %div= msg - .note_text_and_preview.js-toggler-container %a.js-note-preview-button.js-toggler-target.turn-on{ href: "javascript:;", data: {title: "Preview", url: preview_project_notes_path(@project)} } %i.icon-eye-open diff --git a/app/views/notes/_form_errors.html.haml b/app/views/notes/_form_errors.html.haml new file mode 100644 index 00000000000..0851536f0da --- /dev/null +++ b/app/views/notes/_form_errors.html.haml @@ -0,0 +1,3 @@ +.error_message.js-errors + - note.errors.full_messages.each do |msg| + %div= msg diff --git a/app/views/notes/create.js.haml b/app/views/notes/create.js.haml index 6ffb0cdee0e..c573d406b73 100644 --- a/app/views/notes/create.js.haml +++ b/app/views/notes/create.js.haml @@ -7,10 +7,15 @@ - else NoteList.appendNewNote(#{@note.id}, noteHtml); - else - var firstDiscussionNoteHtml = "#{escape_javascript(render "notes/diff_notes_with_reply", notes: [@note])}"; - NoteList.appendNewDiscussionNote("#{@note.discussion_id}", firstDiscussionNoteHtml, noteHtml); + :plain + var firstDiscussionNoteHtml = "#{escape_javascript(render "notes/diff_notes_with_reply", notes: [@note])}"; + NoteList.appendNewDiscussionNote("#{@note.discussion_id}", + firstDiscussionNoteHtml, + noteHtml); - else - -# TODO: insert form correctly - $(".js-main-target-note").replaceWith("#{escape_javascript(render 'notes/common_form')}"); - GitLab.GfmAutoComplete.setup(); \ No newline at end of file + var errorsHtml = "#{escape_javascript(render 'notes/form_errors', note: @note)}"; + - if note_for_main_target?(@note) + NoteList.errorsOnForm(errorsHtml); + - else + NoteList.errorsOnForm(errorsHtml, "#{@note.discussion_id}"); \ No newline at end of file -- cgit v1.2.1 From 4ed8278870640017b93f18b476532824eba70ac2 Mon Sep 17 00:00:00 2001 From: Riyad Preukschas Date: Mon, 3 Dec 2012 21:43:17 +0100 Subject: Fix a bunch of smaller glitches. --- app/assets/javascripts/notes.js | 72 +++++++----------- app/assets/stylesheets/sections/notes.scss | 117 +++++++++++++---------------- app/views/issues/show.html.haml | 2 +- app/views/notes/_form.html.haml | 4 +- 4 files changed, 83 insertions(+), 112 deletions(-) diff --git a/app/assets/javascripts/notes.js b/app/assets/javascripts/notes.js index 8c4577bd1fc..f9dda3c70a1 100644 --- a/app/assets/javascripts/notes.js +++ b/app/assets/javascripts/notes.js @@ -58,12 +58,6 @@ var NoteList = { ".js-close-discussion-note-form", NoteList.removeDiscussionNoteForm); - // do some specific housekeeping when removing a diff or discussion note - $(document).on("click", - ".diff_file .js-note-delete," + - ".discussion .js-note-delete", - NoteList.removeDiscussionNote); - // remove a note (in general) $(document).on("click", ".js-note-delete", @@ -96,9 +90,6 @@ var NoteList = { previewContainer.removeClass("on"); } form.find(".js-note-text").val("").trigger("input"); - - // re-enable submit button - form.find(".js-comment-button").enable(); }, /** @@ -144,8 +135,6 @@ var NoteList = { var preview = form.find('.js-note-preview'); var noteText = form.find('.js-note-text').val(); - console.log("preview", noteText); - if(noteText.trim().length === 0) { preview.text('Nothing to preview.'); } else { @@ -157,36 +146,13 @@ var NoteList = { } }, - /** - * Called in response to deleting a note on a diff line. - * - * Removes the actual note from view. - * Removes the whole notes row if the last note for that line is being removed. - * - * Note: must be called before removeNote() - */ - removeDiscussionNote: function() { - var notes = $(this).closest(".notes"); - - // check if this is the last note for this line - if (notes.find(".note").length === 1) { - // for discussions - notes.closest(".discussion").remove(); - - // for diff lines - notes.closest("tr").remove(); - } - }, - /** * Called in response to "cancel" on a diff note form. * * Shows the reply button again. * Removes the form and if necessary it's temporary row. */ - removeDiscussionNoteForm: function(e) { - e.preventDefault(); - + removeDiscussionNoteForm: function() { var form = $(this).closest("form"); var row = form.closest("tr"); @@ -206,9 +172,22 @@ var NoteList = { * Called in response to deleting a note of any kind. * * Removes the actual note from view. + * Removes the whole discussion if the last note is being removed. */ removeNote: function() { - $(this).closest(".note").remove(); + var note = $(this).closest(".note"); + var notes = note.closest(".notes"); + + // check if this is the last note for this line + if (notes.find(".note").length === 1) { + // for discussions + notes.closest(".discussion").remove(); + + // for diff lines + notes.closest("tr").remove(); + } + + note.remove(); NoteList.updateVotes(); }, @@ -274,6 +253,7 @@ var NoteList = { NoteList.setupNoteForm(form); + form.find(".js-note-text").focus(); }, /** @@ -312,16 +292,18 @@ var NoteList = { setupNoteForm: function(form) { disableButtonIfEmptyField(form.find(".js-note-text"), form.find(".js-comment-button")); + form.removeClass("js-new-note-form"); + // setup preview buttons - $(".js-note-edit-button, .js-note-preview-button").tooltip({ placement: 'left' }); + form.find(".js-note-edit-button, .js-note-preview-button") + .tooltip({ placement: 'left' }); - previewButton = $(".js-note-preview-button"); - previewButton.hide(); + previewButton = form.find(".js-note-preview-button"); form.find(".js-note-text").on("input", function() { if ($(this).val().trim() !== "") { - previewButton.fadeIn(); + previewButton.removeClass("turn-off").addClass("turn-on"); } else { - previewButton.fadeOut(); + previewButton.removeClass("turn-on").addClass("turn-off"); } }); @@ -344,8 +326,8 @@ var NoteList = { $.ajax({ url: NoteList.notes_path, data: NoteList.target_params, - complete: function(){ $('.notes-status').removeClass("loading")}, - beforeSend: function() { $('.notes-status').addClass("loading") }, + complete: function(){ $('.js-notes-busy').removeClass("loading")}, + beforeSend: function() { $('.js-notes-busy').addClass("loading") }, dataType: "script" }); }, @@ -404,8 +386,8 @@ var NoteList = { $.ajax({ url: NoteList.notes_path, data: NoteList.target_params + "&loading_more=1&" + (NoteList.reversed ? "before_id" : "after_id") + "=" + NoteList.bottom_id, - complete: function(){ $('.notes-status').removeClass("loading")}, - beforeSend: function() { $('.notes-status').addClass("loading") }, + complete: function(){ $('.js-notes-busy').removeClass("loading")}, + beforeSend: function() { $('.js-notes-busy').addClass("loading") }, dataType: "script" }); }, diff --git a/app/assets/stylesheets/sections/notes.scss b/app/assets/stylesheets/sections/notes.scss index 6a2f784e72c..981186a5850 100644 --- a/app/assets/stylesheets/sections/notes.scss +++ b/app/assets/stylesheets/sections/notes.scss @@ -135,9 +135,12 @@ ul.notes { } } + + /** - * Discussion/Note Actions + * Actions for Discussions/Notes */ + .discussion, .note { &.note:hover { @@ -174,33 +177,12 @@ ul.notes { top: 0; } -// TODO: start cleaup -.issue_notes, -.wiki_notes { - .note_content { - float: left; - width: 400px; - } -} - -/* for loading indicator */ -.notes-status { - margin: 18px; -} -p.notify_controls input{ - margin: 5px; -} - -p.notify_controls span{ - font-weight: 700; -} -// TODO: end cleaup - /** - * line note button on the side of diffs + * Line note button on the side of diffs */ + .diff_file tr.line_holder { .add-diff-note { background: url("diff_note_add.png") no-repeat left 0; @@ -231,8 +213,10 @@ p.notify_controls span{ } } + + /** - * Note Forms + * Note Form */ .comment-btn, @@ -257,6 +241,46 @@ p.notify_controls span{ line-height: 32px; padding-right: 15px; } + + // TODO: start cleanup + .attachments { + position: relative; + width: 350px; + height: 50px; + overflow: hidden; + margin:0 0 5px !important; + + .input_file { + .file_name { + line-height: 30px; + width: 240px; + height: 28px; + overflow: hidden; + } + .file_upload { + position: absolute; + right:14px; + top:7px; + } + .input-file { + width: 260px; + height: 41px; + float: right; + } + } + } + .input-file { + font: 500px monospace; + opacity:0; + filter: alpha(opacity=0); + position: absolute; + z-index: 1; + top:0; + right:0; + padding:0; + margin: 0; + } + // TODO: end cleanup } .note_text_and_preview { // makes the "absolute" position for links relative to this @@ -282,44 +306,9 @@ p.notify_controls span{ width: 98.6%; } } +} - // TODO: start cleanup - .attachments { - position: relative; - width: 350px; - height: 50px; - overflow: hidden; - margin:0 0 5px !important; - - .input_file { - .file_name { - line-height: 30px; - width: 240px; - height: 28px; - overflow: hidden; - } - .file_upload { - position: absolute; - right:14px; - top:7px; - } - .input-file { - width: 260px; - height: 41px; - float: right; - } - } - } - .input-file { - font: 500px monospace; - opacity:0; - filter: alpha(opacity=0); - position: absolute; - z-index: 1; - top:0; - right:0; - padding:0; - margin: 0; - } - // TODO: end cleanup +/* loading indicator */ +.notes-busy { + margin: 18px; } diff --git a/app/views/issues/show.html.haml b/app/views/issues/show.html.haml index a52d1134acc..3d3164fed20 100644 --- a/app/views/issues/show.html.haml +++ b/app/views/issues/show.html.haml @@ -61,4 +61,4 @@ = markdown @issue.description -.issue_notes.voting_notes#notes= render "notes/notes_with_form" +.voting_notes#notes= render "notes/notes_with_form" diff --git a/app/views/notes/_form.html.haml b/app/views/notes/_form.html.haml index f4a79b0b196..cb96877f766 100644 --- a/app/views/notes/_form.html.haml +++ b/app/views/notes/_form.html.haml @@ -6,7 +6,7 @@ = f.hidden_field :noteable_type .note_text_and_preview.js-toggler-container - %a.js-note-preview-button.js-toggler-target.turn-on{ href: "javascript:;", data: {title: "Preview", url: preview_project_notes_path(@project)} } + %a.js-note-preview-button.js-toggler-target.turn-off{ href: "javascript:;", data: {title: "Preview", url: preview_project_notes_path(@project)} } %i.icon-eye-open %a.js-note-edit-button.js-toggler-target.turn-off{ href: "javascript:;", data: {title: "Edit"} } %i.icon-edit @@ -37,7 +37,7 @@ = check_box_tag :notify, 1, !@note.for_commit? %span Project team - - if @note.notify_only_author?(current_user) + - if @note.notify_only_author?(current_user) # FIXME: put in JS = label_tag :notify_author do = check_box_tag :notify_author, 1 , !@note.for_commit? %span Commit author -- cgit v1.2.1 From b47173da6a0fea0982d009f91e2c4d042f9b5c37 Mon Sep 17 00:00:00 2001 From: Riyad Preukschas Date: Mon, 3 Dec 2012 22:34:50 +0100 Subject: Revamped note form options. --- app/assets/javascripts/notes.js | 89 +++++++++++++++++++++--------- app/assets/stylesheets/sections/notes.scss | 59 +++++++++----------- app/models/note.rb | 18 ------ app/views/notes/_form.html.haml | 23 ++++---- 4 files changed, 100 insertions(+), 89 deletions(-) diff --git a/app/assets/javascripts/notes.js b/app/assets/javascripts/notes.js index f9dda3c70a1..fa0edd2d1f4 100644 --- a/app/assets/javascripts/notes.js +++ b/app/assets/javascripts/notes.js @@ -32,12 +32,6 @@ var NoteList = { // get initial set of notes NoteList.getContent(); - $("#note_attachment").change(function(e){ - var val = $('.input-file').val(); - var filename = val.replace(/^.*[\\\/]/, ''); - $(".file_name").text(filename); - }); - // add a new diff note $(document).on("click", ".js-add-diff-note-button", @@ -53,6 +47,11 @@ var NoteList = { ".js-note-preview-button", NoteList.previewNote); + // update the file name when an attachment is selected + $(document).on("change", + ".js-note-attachment-input", + NoteList.updateFormAttachment); + // hide diff note form $(document).on("click", ".js-close-discussion-note-form", @@ -63,34 +62,21 @@ var NoteList = { ".js-note-delete", NoteList.removeNote); - // clean up previews for main target form + // reset main target form after submit $(document).on("ajax:complete", ".js-main-target-form", - NoteList.cleanupMainTargetForm); - }, + NoteList.resetMainTargetForm); - /** - * Event handlers - */ + $(document).on("click", + ".js-choose-note-attachment-button", + NoteList.chooseNoteAttachment); + }, /** - * + * When clicking on buttons */ - cleanupMainTargetForm: function(){ - var form = $(this); - - // remove validation errors - form.find(".js-errors").remove(); - - // reset text and preview - var previewContainer = form.find(".js-toggler-container.note_text_and_preview"); - if (previewContainer.is(".on")) { - previewContainer.removeClass("on"); - } - form.find(".js-note-text").val("").trigger("input"); - }, /** * Called when clicking on the "add a comment" button on the side of a diff line. @@ -121,6 +107,17 @@ var NoteList = { } }, + /** + * Called when clicking the "Choose File" button. + * + * Opesn the file selection dialog. + */ + chooseNoteAttachment: function() { + var form = $(this).closest("form"); + + form.find(".js-note-attachment-input").click(); + }, + /** * Shows the note preview. * @@ -307,6 +304,11 @@ var NoteList = { } }); + // remove notify commit author checkbox for non-commit notes + if (form.find("#note_noteable_type").val() !== "Commit") { + form.find(".js-notify-commit-author").remove(); + } + GitLab.GfmAutoComplete.setup(); form.show(); @@ -499,6 +501,41 @@ var NoteList = { $("#new-notes-list").prepend(html); }, + /** + * Called in response the main target form has been successfully submitted. + * + * Removes any errors. + * Resets text and preview. + * Resets buttons. + */ + resetMainTargetForm: function(){ + var form = $(this); + + // remove validation errors + form.find(".js-errors").remove(); + + // reset text and preview + var previewContainer = form.find(".js-toggler-container.note_text_and_preview"); + if (previewContainer.is(".on")) { + previewContainer.removeClass("on"); + } + form.find(".js-note-text").val("").trigger("input"); + }, + + /** + * Called after an attachment file has been selected. + * + * Updates the file name for the selected attachment. + */ + updateFormAttachment: function() { + var form = $(this).closest("form"); + + // get only the basename + var filename = $(this).val().replace(/^.*[\\\/]/, ''); + + form.find(".js-attachment-filename").text(filename); + }, + /** * Recalculates the votes and updates them (if they are displayed at all). * diff --git a/app/assets/stylesheets/sections/notes.scss b/app/assets/stylesheets/sections/notes.scss index 981186a5850..465d578f3b7 100644 --- a/app/assets/stylesheets/sections/notes.scss +++ b/app/assets/stylesheets/sections/notes.scss @@ -227,6 +227,11 @@ ul.notes { .discussion { .new_note { margin: 8px 5px 8px 0; + + .note_options { + // because of the smaller width and the extra "cancel" button + margin-top: 8px; + } } } .new_note { @@ -236,51 +241,39 @@ ul.notes { float: left; margin-top: 8px; } + .clearfix { + margin-bottom: 0; + } .note_options { h6 { - line-height: 32px; - padding-right: 15px; + @extend .left; + line-height: 20px; + padding-right: 16px; + padding-bottom: 16px; + } + label { + padding: 0; } - // TODO: start cleanup - .attachments { + .attachment { + @extend .right; position: relative; width: 350px; height: 50px; - overflow: hidden; margin:0 0 5px !important; - .input_file { - .file_name { - line-height: 30px; - width: 240px; - height: 28px; - overflow: hidden; - } - .file_upload { - position: absolute; - right:14px; - top:7px; - } - .input-file { - width: 260px; - height: 41px; - float: right; - } + // hide the actual file field + input { + display: none; + } + + .choose-btn { + float: right; } } - .input-file { - font: 500px monospace; - opacity:0; - filter: alpha(opacity=0); - position: absolute; - z-index: 1; - top:0; - right:0; - padding:0; - margin: 0; + .notify_options { + @extend .right; } - // TODO: end cleanup } .note_text_and_preview { // makes the "absolute" position for links relative to this diff --git a/app/models/note.rb b/app/models/note.rb index 0027c57b63b..a8ae9080627 100644 --- a/app/models/note.rb +++ b/app/models/note.rb @@ -140,24 +140,6 @@ class Note < ActiveRecord::Base @notify_author ||= false end - # Check if we can notify commit author - # with email about our comment - # - # If commit author email exist in project - # and commit author is not passed user we can - # send email to him - # - # params: - # user - current user - # - # return: - # Boolean - # - def notify_only_author?(user) - for_commit? && commit_author && - commit_author.email != user.email - end - # Returns true if this is an upvote note, # otherwise false is returned def upvote? diff --git a/app/views/notes/_form.html.haml b/app/views/notes/_form.html.haml index cb96877f766..57811daf919 100644 --- a/app/views/notes/_form.html.haml +++ b/app/views/notes/_form.html.haml @@ -22,23 +22,22 @@ .clearfix .note_options - .attachments.right - %h6.left Attachment: - %span.file_name File name... + .attachment + %h6 Attachment: + .file_name.js-attachment-filename File name... + %a.choose-btn.btn.small.js-choose-note-attachment-button Choose File ... + .hint Any file up to 10 MB - .input.input_file - %a.file_upload.btn.small Upload File - = f.file_field :attachment, class: "input-file" - %span.hint Any file less than 10 MB + = f.file_field :attachment, class: "js-note-attachment-input" - .notify_opts.right - %h6.left Notify via email: + .notify_options + %h6 Notify via email: = label_tag :notify do = check_box_tag :notify, 1, !@note.for_commit? - %span Project team + Project team - - if @note.notify_only_author?(current_user) # FIXME: put in JS + .js-notify-commit-author = label_tag :notify_author do = check_box_tag :notify_author, 1 , !@note.for_commit? - %span Commit author + Commit author .clearfix -- cgit v1.2.1 From 7335f366dc952aa371e1e17cfbe2874d51dd6f16 Mon Sep 17 00:00:00 2001 From: Riyad Preukschas Date: Wed, 2 Jan 2013 20:49:27 +0100 Subject: Fix comment and reply buttons --- app/assets/javascripts/notes.js | 1 + app/controllers/commit_controller.rb | 2 +- app/views/notes/_diff_note_link.html.haml | 1 + app/views/notes/_discussion_reply_button.html.haml | 1 + 4 files changed, 4 insertions(+), 1 deletion(-) diff --git a/app/assets/javascripts/notes.js b/app/assets/javascripts/notes.js index fa0edd2d1f4..1eac462172b 100644 --- a/app/assets/javascripts/notes.js +++ b/app/assets/javascripts/notes.js @@ -244,6 +244,7 @@ var NoteList = { setupDiscussionNoteForm: function(dataHolder, form) { // setup note target form.attr("rel", dataHolder.data("discussionId")); + form.find("#note_commit_id").val(dataHolder.data("commitId")); form.find("#note_line_code").val(dataHolder.data("lineCode")); form.find("#note_noteable_type").val(dataHolder.data("noteableType")); form.find("#note_noteable_id").val(dataHolder.data("noteableId")); diff --git a/app/controllers/commit_controller.rb b/app/controllers/commit_controller.rb index 4fbfe205d3f..1329410891d 100644 --- a/app/controllers/commit_controller.rb +++ b/app/controllers/commit_controller.rb @@ -23,7 +23,7 @@ class CommitController < ProjectResourceController @comments_allowed = @reply_allowed = true @comments_target = { noteable_type: 'Commit', - noteable_id: @commit.id } + commit_id: @commit.id } respond_to do |format| format.html do diff --git a/app/views/notes/_diff_note_link.html.haml b/app/views/notes/_diff_note_link.html.haml index 56eeeb102eb..377c926a204 100644 --- a/app/views/notes/_diff_note_link.html.haml +++ b/app/views/notes/_diff_note_link.html.haml @@ -4,6 +4,7 @@ class: "add-diff-note js-add-diff-note-button", data: { noteable_type: note.noteable_type, noteable_id: note.noteable_id, + commit_id: note.commit_id, line_code: note.line_code, discussion_id: note.discussion_id }, title: "Add a comment to this line" diff --git a/app/views/notes/_discussion_reply_button.html.haml b/app/views/notes/_discussion_reply_button.html.haml index 15b68560955..d1c5ccc29db 100644 --- a/app/views/notes/_discussion_reply_button.html.haml +++ b/app/views/notes/_discussion_reply_button.html.haml @@ -2,6 +2,7 @@ class: "btn reply-btn js-discussion-reply-button", data: { noteable_type: note.noteable_type, noteable_id: note.noteable_id, + commit_id: note.commit_id, line_code: note.line_code, discussion_id: note.discussion_id }, title: "Add a reply" do -- cgit v1.2.1 From 621c6b8533b527c735bb90c0a49ed18f55af93fa Mon Sep 17 00:00:00 2001 From: Riyad Preukschas Date: Wed, 2 Jan 2013 20:50:24 +0100 Subject: Fix commit note notification --- app/mailers/notify.rb | 4 ++-- app/observers/note_observer.rb | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/mailers/notify.rb b/app/mailers/notify.rb index 5cd9b82900c..7d68e50b382 100644 --- a/app/mailers/notify.rb +++ b/app/mailers/notify.rb @@ -62,12 +62,12 @@ class Notify < ActionMailer::Base # Note # - def note_commit_email(recipient_id, note_id) + def note_commit_email(commit_autor_email, note_id) @note = Note.find(note_id) @commit = @note.noteable @commit = CommitDecorator.decorate(@commit) @project = @note.project - mail(to: recipient(recipient_id), subject: subject("note for commit #{@commit.short_id}", @commit.title)) + mail(to: recipient(commit_autor_email), subject: subject("note for commit #{@commit.short_id}", @commit.title)) end def note_issue_email(recipient_id, note_id) diff --git a/app/observers/note_observer.rb b/app/observers/note_observer.rb index fe01efcaac2..0a353cf1092 100644 --- a/app/observers/note_observer.rb +++ b/app/observers/note_observer.rb @@ -11,7 +11,7 @@ class NoteObserver < ActiveRecord::Observer notify_team(note) elsif note.notify_author # Notify only author of resource - Notify.note_commit_email(note.commit_author.id, note.id).deliver + Notify.note_commit_email(note.noteable.author_email, note.id).deliver else # Otherwise ignore it nil -- cgit v1.2.1 From e29687552e375d324a153de077e0dbe7a4a5fd3c Mon Sep 17 00:00:00 2001 From: Riyad Preukschas Date: Wed, 2 Jan 2013 21:07:02 +0100 Subject: Fix link titles --- app/views/notes/_form.html.haml | 4 ++-- app/views/notes/_note.html.haml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/views/notes/_form.html.haml b/app/views/notes/_form.html.haml index c310fac47ca..38bb8a22cb5 100644 --- a/app/views/notes/_form.html.haml +++ b/app/views/notes/_form.html.haml @@ -7,9 +7,9 @@ = f.hidden_field :noteable_type .note_text_and_preview.js-toggler-container - %a.js-note-preview-button.js-toggler-target.turn-off{ href: "javascript:;", data: {title: "Preview", url: preview_project_notes_path(@project)} } + %a.js-note-preview-button.js-toggler-target.turn-off{ href: "javascript:;", title: "Preview", data: {url: preview_project_notes_path(@project)} } %i.icon-eye-open - %a.js-note-edit-button.js-toggler-target.turn-off{ href: "javascript:;", data: {title: "Edit"} } + %a.js-note-edit-button.js-toggler-target.turn-off{ href: "javascript:;", title: "Edit" } %i.icon-edit = f.text_area :note, size: 255, class: 'note_text js-note-text js-gfm-input turn-on' diff --git a/app/views/notes/_note.html.haml b/app/views/notes/_note.html.haml index 980300c4657..8881cf5a847 100644 --- a/app/views/notes/_note.html.haml +++ b/app/views/notes/_note.html.haml @@ -6,7 +6,7 @@ Link here   - if(note.author_id == current_user.id) || can?(current_user, :admin_note, @project) - = link_to project_note_path(@project, note), method: :delete, confirm: 'Are you sure?', remote: true, class: "danger js-note-delete" do + = link_to project_note_path(@project, note), title: "Remove comment", method: :delete, confirm: 'Are you sure?', remote: true, class: "danger js-note-delete" do %i.icon-remove-circle = image_tag gravatar_icon(note.author.email), class: "avatar s32" = link_to note.author_name, project_team_member_path(@project, @project.team_member_by_id(note.author)), class: "note-author" -- cgit v1.2.1 From 6c724ed96c4666efc0994f81c97dc40a7580f927 Mon Sep 17 00:00:00 2001 From: Riyad Preukschas Date: Wed, 2 Jan 2013 21:31:48 +0100 Subject: Fix factories --- spec/factories.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/factories.rb b/spec/factories.rb index 44fb9378870..9e16bc9e3a9 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -95,17 +95,17 @@ FactoryGirl.define do author factory :note_on_commit, traits: [:on_commit] - factory :note_on_commit_line, traits: [:on_commit, :on_line] + factory :note_on_commit_diff, traits: [:on_commit, :on_diff] factory :note_on_issue, traits: [:on_issue], aliases: [:votable_note] factory :note_on_merge_request, traits: [:on_merge_request] - factory :note_on_merge_request_line, traits: [:on_merge_request, :on_line] + factory :note_on_merge_request_diff, traits: [:on_merge_request, :on_diff] trait :on_commit do commit_id "bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a" noteable_type "Commit" end - trait :on_line do + trait :on_diff do line_code "0_184_184" end -- cgit v1.2.1 From 1883e0830cb9a8803e98059c9f4c6c82b55c5d84 Mon Sep 17 00:00:00 2001 From: Riyad Preukschas Date: Sat, 5 Jan 2013 22:58:27 +0100 Subject: Add specs for notes on commits --- spec/requests/notes_on_commits_spec.rb | 223 +++++++++++++++++++++++++++++++++ 1 file changed, 223 insertions(+) create mode 100644 spec/requests/notes_on_commits_spec.rb diff --git a/spec/requests/notes_on_commits_spec.rb b/spec/requests/notes_on_commits_spec.rb new file mode 100644 index 00000000000..cba41c4df00 --- /dev/null +++ b/spec/requests/notes_on_commits_spec.rb @@ -0,0 +1,223 @@ +require 'spec_helper' + +describe "On a commit", js: true do + let!(:project) { create(:project) } + let!(:commit) { project.commit("bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a") } + + before do + login_as :user + project.add_access(@user, :read, :write) + + visit project_commit_path(project, commit) + end + + subject { page } + + describe "the note form" do + # main target form creation + it { should have_css(".js-main-target-form", visible: true, count: 1) } + + # button initalization + it { within(".js-main-target-form") { should have_button("Add Comment") } } + it { within(".js-main-target-form") { should_not have_link("Cancel") } } + + # notifiactions + it { within(".js-main-target-form") { should have_unchecked_field("Project team") } } + it { within(".js-main-target-form") { should have_checked_field("Commit author") } } + + describe "without text" do + it { within(".js-main-target-form") { should have_css(".js-note-preview-button", visible: false) } } + end + + describe "with text" do + before do + within(".js-main-target-form") do + fill_in "note[note]", with: "This is awesome" + end + end + + it { within(".js-main-target-form") { should_not have_css(".js-comment-button[disabled]") } } + + it { within(".js-main-target-form") { should have_css(".js-note-preview-button", visible: true) } } + end + + describe "with preview" do + before do + within(".js-main-target-form") do + fill_in "note[note]", with: "This is awesome" + find(".js-note-preview-button").trigger("click") + end + end + + it { within(".js-main-target-form") { should have_css(".js-note-preview", text: "This is awesome", visible: true) } } + + it { within(".js-main-target-form") { should have_css(".js-note-preview-button", visible: false) } } + it { within(".js-main-target-form") { should have_css(".js-note-edit-button", visible: true) } } + end + end + + describe "when posting a note" do + before do + within(".js-main-target-form") do + fill_in "note[note]", with: "This is awsome!" + find(".js-note-preview-button").trigger("click") + click_button "Add Comment" + end + end + + # note added + it { within(".js-main-target-form") { should have_content("This is awsome!") } } + + # reset form + it { within(".js-main-target-form") { should have_no_field("note[note]", with: "This is awesome!") } } + + # return from preview + it { within(".js-main-target-form") { should have_css(".js-note-preview", visible: false) } } + it { within(".js-main-target-form") { should have_css(".js-note-text", visible: true) } } + + + it "should be removable" do + find(".js-note-delete").trigger("click") + + should_not have_css(".note") + end + end +end + + + +describe "On a commit diff", js: true do + let!(:project) { create(:project) } + let!(:commit) { project.commit("bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a") } + + before do + login_as :user + project.add_access(@user, :read, :write) + + visit project_commit_path(project, commit) + end + + subject { page } + + describe "when adding a note" do + before do + find("#0_185_185.line_holder .js-add-diff-note-button").trigger("click") + end + + describe "the notes holder" do + it { should have_css("#0_185_185.line_holder + .js-temp-notes-holder") } + + it { within(".js-temp-notes-holder") { should have_css(".new_note") } } + end + + describe "the note form" do + # set up hidden fields correctly + it { within(".js-temp-notes-holder") { find("#note_noteable_type").value.should == "Commit" } } + it { within(".js-temp-notes-holder") { find("#note_noteable_id").value.should == "" } } + it { within(".js-temp-notes-holder") { find("#note_commit_id").value.should == "bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a" } } + it { within(".js-temp-notes-holder") { find("#note_line_code").value.should == "0_185_185" } } + + # buttons + it { should have_button("Add Comment") } + it { should have_css(".js-close-discussion-note-form", text: "Cancel") } + + # notification options + it { should have_unchecked_field("Project team") } + it { should have_checked_field("Commit author") } + + it "shouldn't add a second form for same row" do + find("#0_185_185.line_holder .js-add-diff-note-button").trigger("click") + + should have_css("#0_185_185.line_holder + .js-temp-notes-holder form", count: 1) + end + + it "should be removed when canceled" do + find(".js-close-discussion-note-form").trigger("click") + + should have_no_css(".js-temp-notes-holder") + end + end + end + + describe "with muliple note forms" do + before do + find("#0_185_185.line_holder .js-add-diff-note-button").trigger("click") + find("#1_18_17.line_holder .js-add-diff-note-button").trigger("click") + end + + # has two line forms + it { should have_css(".js-temp-notes-holder", count: 2) } + + describe "previewing them separately" do + before do + # add two separate texts and trigger previews on both + within("#0_185_185.line_holder + .js-temp-notes-holder") do + fill_in "note[note]", with: "One comment on line 185" + find(".js-note-preview-button").trigger("click") + end + within("#1_18_17.line_holder + .js-temp-notes-holder") do + fill_in "note[note]", with: "Another comment on line 17" + find(".js-note-preview-button").trigger("click") + end + end + + # check if previews were rendered separately + it { within("#0_185_185.line_holder + .js-temp-notes-holder") { should have_css(".js-note-preview", text: "One comment on line 185") } } + it { within("#1_18_17.line_holder + .js-temp-notes-holder") { should have_css(".js-note-preview", text: "Another comment on line 17") } } + end + + describe "posting a note" do + before do + within("#1_18_17.line_holder + .js-temp-notes-holder") do + fill_in "note[note]", with: "Another comment on line 17" + click_button("Add Comment") + end + end + + # removed form after submit + it { should have_no_css("#1_18_17.line_holder + .js-temp-notes-holder") } + + # added discussion + it { should have_content("Another comment on line 17") } + it { should have_css("#1_18_17.line_holder + .notes_holder") } + it { should have_css("#1_18_17.line_holder + .notes_holder .note", count: 1) } + it { should have_link("Reply") } + + it "should remove last note of a discussion" do + within("#1_18_17.line_holder + .notes_holder") do + find(".js-note-delete").trigger("click") + end + + # removed whole discussion + should_not have_css(".note_holder") + should have_css("#1_18_17.line_holder + #1_18_18.line_holder") + end + end + end + + describe "when replying to a note" do + before do + # create first note + find("#0_184_184.line_holder .js-add-diff-note-button").trigger("click") + within("#0_184_184.line_holder + .js-temp-notes-holder") do + fill_in "note[note]", with: "One comment on line 184" + click_button("Add Comment") + end + # create second note + within("#0_184_184.line_holder + .notes_holder") do + find(".js-discussion-reply-button").trigger("click") + fill_in "note[note]", with: "An additional comment in reply" + click_button("Add Comment") + end + end + + # inserted note + it { should have_content("An additional comment in reply") } + it { within("#0_184_184.line_holder + .notes_holder") { should have_css(".note", count: 2) } } + + # removed form after reply + it { within("#0_184_184.line_holder + .notes_holder") { should have_no_css("form") } } + it { within("#0_184_184.line_holder + .notes_holder") { should have_link("Reply") } } + end +end + \ No newline at end of file -- cgit v1.2.1 From 8c604c9d31561dc364173626923d568bf76414ba Mon Sep 17 00:00:00 2001 From: Riyad Preukschas Date: Sat, 5 Jan 2013 22:58:36 +0100 Subject: Add specs for notes on wall --- spec/requests/notes_on_wall_spec.rb | 86 +++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 spec/requests/notes_on_wall_spec.rb diff --git a/spec/requests/notes_on_wall_spec.rb b/spec/requests/notes_on_wall_spec.rb new file mode 100644 index 00000000000..b42d293f9d6 --- /dev/null +++ b/spec/requests/notes_on_wall_spec.rb @@ -0,0 +1,86 @@ +require 'spec_helper' + +describe "On the project wall", js: true do + let!(:project) { create(:project) } + let!(:commit) { project.commit("bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a") } + + before do + login_as :user + project.add_access(@user, :read, :write) + + visit wall_project_path(project) + end + + subject { page } + + describe "the note form" do + # main target form creation + it { should have_css(".js-main-target-form", visible: true, count: 1) } + + # button initalization + it { within(".js-main-target-form") { should have_button("Add Comment") } } + it { within(".js-main-target-form") { should_not have_link("Cancel") } } + + # notifiactions + it { within(".js-main-target-form") { should have_checked_field("Project team") } } + it { within(".js-main-target-form") { should_not have_checked_field("Commit author") } } + it { within(".js-main-target-form") { should_not have_unchecked_field("Commit author") } } + + describe "without text" do + it { within(".js-main-target-form") { should have_css(".js-note-preview-button", visible: false) } } + end + + describe "with text" do + before do + within(".js-main-target-form") do + fill_in "note[note]", with: "This is awesome" + end + end + + it { within(".js-main-target-form") { should_not have_css(".js-comment-button[disabled]") } } + + it { within(".js-main-target-form") { should have_css(".js-note-preview-button", visible: true) } } + end + + describe "with preview" do + before do + within(".js-main-target-form") do + fill_in "note[note]", with: "This is awesome" + find(".js-note-preview-button").trigger("click") + end + end + + it { within(".js-main-target-form") { should have_css(".js-note-preview", text: "This is awesome", visible: true) } } + + it { within(".js-main-target-form") { should have_css(".js-note-preview-button", visible: false) } } + it { within(".js-main-target-form") { should have_css(".js-note-edit-button", visible: true) } } + end + end + + describe "when posting a note" do + before do + within(".js-main-target-form") do + fill_in "note[note]", with: "This is awsome!" + find(".js-note-preview-button").trigger("click") + click_button "Add Comment" + end + end + + # note added + it { within(".js-main-target-form") { should have_content("This is awsome!") } } + + # reset form + it { within(".js-main-target-form") { should have_no_field("note[note]", with: "This is awesome!") } } + + # return from preview + it { within(".js-main-target-form") { should have_css(".js-note-preview", visible: false) } } + it { within(".js-main-target-form") { should have_css(".js-note-text", visible: true) } } + + + it "should be removable" do + find(".js-note-delete").trigger("click") + + should_not have_css(".note") + end + end +end -- cgit v1.2.1 From 74e48f070f5adb83c0d82ca5b8795bebb666033e Mon Sep 17 00:00:00 2001 From: Riyad Preukschas Date: Tue, 15 Jan 2013 00:27:26 +0100 Subject: Smaller fixes --- app/views/notes/_form.html.haml | 2 +- spec/factories.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/views/notes/_form.html.haml b/app/views/notes/_form.html.haml index 38bb8a22cb5..d094119a9da 100644 --- a/app/views/notes/_form.html.haml +++ b/app/views/notes/_form.html.haml @@ -39,6 +39,6 @@ .js-notify-commit-author = label_tag :notify_author do - = check_box_tag :notify_author, 1 , !@note.for_commit? + = check_box_tag :notify_author, 1 , @note.for_commit? Commit author .clearfix diff --git a/spec/factories.rb b/spec/factories.rb index 9e16bc9e3a9..ca75e507077 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -73,8 +73,8 @@ FactoryGirl.define do # pick 3 commits "at random" (from bcf03b5d~3 to bcf03b5d) trait :with_diffs do - target_branch "bcf03b5d~3" - source_branch "bcf03b5d" + target_branch "master" # pretend bcf03b5d~3 + source_branch "stable" # pretend bcf03b5d st_commits do [Commit.new(project.repo.commit('bcf03b5d')), Commit.new(project.repo.commit('bcf03b5d~1')), -- cgit v1.2.1 From 8ee5fce9d64b70d8981896457484fae622d142c9 Mon Sep 17 00:00:00 2001 From: Riyad Preukschas Date: Tue, 15 Jan 2013 00:27:59 +0100 Subject: Add preliminary specs for notes on merge requests --- spec/requests/notes_on_merge_requests_spec.rb | 235 ++++++++++++++++++++++++++ 1 file changed, 235 insertions(+) create mode 100644 spec/requests/notes_on_merge_requests_spec.rb diff --git a/spec/requests/notes_on_merge_requests_spec.rb b/spec/requests/notes_on_merge_requests_spec.rb new file mode 100644 index 00000000000..e10a7f2c2e2 --- /dev/null +++ b/spec/requests/notes_on_merge_requests_spec.rb @@ -0,0 +1,235 @@ +require 'spec_helper' + +describe "On a merge request", js: true do + let!(:project) { create(:project) } + let!(:merge_request) { create(:merge_request, project: project) } + + before do + login_as :user + project.add_access(@user, :read, :write) + + visit project_merge_request_path(project, merge_request) + end + + subject { page } + + describe "the note form" do + # main target form creation + it { should have_css(".js-main-target-form", visible: true, count: 1) } + + # button initalization + it { within(".js-main-target-form") { should have_button("Add Comment") } } + it { within(".js-main-target-form") { should_not have_link("Cancel") } } + + # notifiactions + it { within(".js-main-target-form") { should have_checked_field("Project team") } } + it { within(".js-main-target-form") { should_not have_checked_field("Commit author") } } + it { within(".js-main-target-form") { should_not have_unchecked_field("Commit author") } } + + describe "without text" do + it { within(".js-main-target-form") { should have_css(".js-note-preview-button", visible: false) } } + end + + describe "with text" do + before do + within(".js-main-target-form") do + fill_in "note[note]", with: "This is awesome" + end + end + + it { within(".js-main-target-form") { should_not have_css(".js-comment-button[disabled]") } } + + it { within(".js-main-target-form") { should have_css(".js-note-preview-button", visible: true) } } + end + + describe "with preview" do + before do + within(".js-main-target-form") do + fill_in "note[note]", with: "This is awesome" + find(".js-note-preview-button").trigger("click") + end + end + + it { within(".js-main-target-form") { should have_css(".js-note-preview", text: "This is awesome", visible: true) } } + + it { within(".js-main-target-form") { should have_css(".js-note-preview-button", visible: false) } } + it { within(".js-main-target-form") { should have_css(".js-note-edit-button", visible: true) } } + end + end + + describe "when posting a note" do + before do + within(".js-main-target-form") do + fill_in "note[note]", with: "This is awsome!" + find(".js-note-preview-button").trigger("click") + click_button "Add Comment" + end + end + + # note added + it { within(".js-main-target-form") { should have_content("This is awsome!") } } + + # reset form + it { within(".js-main-target-form") { should have_no_field("note[note]", with: "This is awesome!") } } + + # return from preview + it { within(".js-main-target-form") { should have_css(".js-note-preview", visible: false) } } + it { within(".js-main-target-form") { should have_css(".js-note-text", visible: true) } } + + + it "should be removable" do + find(".js-note-delete").trigger("click") + + should_not have_css(".note") + end + end +end + + + +describe "On a merge request diff", js: true, focus: true do + let!(:project) { create(:project) } + let!(:merge_request) { create(:merge_request_with_diffs, project: project) } + + before(:all) do + login_as :user + project.add_access(@user, :read, :write) + + visit project_merge_request_diff_path(project, merge_request) + + save_and_open_page + + click_link("Diff") + end + + subject { page } + + describe "when adding a note" do + before do + find("#0_185_185.line_holder .js-add-diff-note-button").trigger("click") + end + + describe "the notes holder" do + it { should have_css("#0_185_185.line_holder + .js-temp-notes-holder") } + + it { within(".js-temp-notes-holder") { should have_css(".new_note") } } + end + + describe "the note form" do + # set up hidden fields correctly + it { within(".js-temp-notes-holder") { find("#note_noteable_type").value.should == "Commit" } } + it { within(".js-temp-notes-holder") { find("#note_noteable_id").value.should == "" } } + it { within(".js-temp-notes-holder") { find("#note_commit_id").value.should == "bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a" } } + it { within(".js-temp-notes-holder") { find("#note_line_code").value.should == "0_185_185" } } + + # buttons + it { should have_button("Add Comment") } + it { should have_css(".js-close-discussion-note-form", text: "Cancel") } + + # notification options + it { should have_unchecked_field("Project team") } + it { should have_checked_field("Commit author") } + + it "shouldn't add a second form for same row" do + find("#0_185_185.line_holder .js-add-diff-note-button").trigger("click") + + should have_css("#0_185_185.line_holder + .js-temp-notes-holder form", count: 1) + end + + it "should be removed when canceled" do + find(".js-close-discussion-note-form").trigger("click") + + should have_no_css(".js-temp-notes-holder") + end + end + end + + describe "with muliple note forms" do + before do + find("#0_185_185.line_holder .js-add-diff-note-button").trigger("click") + find("#1_18_17.line_holder .js-add-diff-note-button").trigger("click") + end + + # has two line forms + it { should have_css(".js-temp-notes-holder", count: 2) } + + describe "previewing them separately" do + before do + # add two separate texts and trigger previews on both + within("#0_185_185.line_holder + .js-temp-notes-holder") do + fill_in "note[note]", with: "One comment on line 185" + find(".js-note-preview-button").trigger("click") + end + within("#1_18_17.line_holder + .js-temp-notes-holder") do + fill_in "note[note]", with: "Another comment on line 17" + find(".js-note-preview-button").trigger("click") + end + end + + # check if previews were rendered separately + it { within("#0_185_185.line_holder + .js-temp-notes-holder") { should have_css(".js-note-preview", text: "One comment on line 185") } } + it { within("#1_18_17.line_holder + .js-temp-notes-holder") { should have_css(".js-note-preview", text: "Another comment on line 17") } } + end + + describe "posting a note" do + before do + within("#1_18_17.line_holder + .js-temp-notes-holder") do + fill_in "note[note]", with: "Another comment on line 17" + click_button("Add Comment") + end + end + + # removed form after submit + it { should have_no_css("#1_18_17.line_holder + .js-temp-notes-holder") } + + # added discussion + it { should have_content("Another comment on line 17") } + it { should have_css("#1_18_17.line_holder + .notes_holder") } + it { should have_css("#1_18_17.line_holder + .notes_holder .note", count: 1) } + it { should have_link("Reply") } + + it "should remove last note of a discussion" do + within("#1_18_17.line_holder + .notes_holder") do + find(".js-note-delete").trigger("click") + end + + # removed whole discussion + should_not have_css(".note_holder") + should have_css("#1_18_17.line_holder + #1_18_18.line_holder") + end + end + end + + describe "when replying to a note" do + before do + # create first note + find("#0_184_184.line_holder .js-add-diff-note-button").trigger("click") + within("#0_184_184.line_holder + .js-temp-notes-holder") do + fill_in "note[note]", with: "One comment on line 184" + click_button("Add Comment") + end + # create second note + within("#0_184_184.line_holder + .notes_holder") do + find(".js-discussion-reply-button").trigger("click") + fill_in "note[note]", with: "An additional comment in reply" + click_button("Add Comment") + end + end + + # inserted note + it { should have_content("An additional comment in reply") } + it { within("#0_184_184.line_holder + .notes_holder") { should have_css(".note", count: 2) } } + + # removed form after reply + it { within("#0_184_184.line_holder + .notes_holder") { should have_no_css("form") } } + it { within("#0_184_184.line_holder + .notes_holder") { should have_link("Reply") } } + end +end + + + +describe "On merge request discussion", js: true do + describe "with merge request diff note" + describe "with commit note" + describe "with commit diff note" +end \ No newline at end of file -- cgit v1.2.1 From f8e1f4a7c9ee2554efcf7376a0cfbefae8956d7b Mon Sep 17 00:00:00 2001 From: Riyad Preukschas Date: Mon, 14 Jan 2013 23:55:02 +0100 Subject: Replace commit note request specs with spinach features --- features/project/commits/commit_comments.feature | 46 +++++++++- features/steps/project/comments_on_commits.rb | 6 ++ features/steps/project/project_comment_commit.rb | 6 -- features/steps/shared/note.rb | 105 +++++++++++++++++++++-- spec/requests/notes_on_commits_spec.rb | 90 +------------------ 5 files changed, 149 insertions(+), 104 deletions(-) create mode 100644 features/steps/project/comments_on_commits.rb delete mode 100644 features/steps/project/project_comment_commit.rb diff --git a/features/project/commits/commit_comments.feature b/features/project/commits/commit_comments.feature index 5acf541ab96..a1aa745a681 100644 --- a/features/project/commits/commit_comments.feature +++ b/features/project/commits/commit_comments.feature @@ -1,10 +1,48 @@ -Feature: Project Comment commit +Feature: Comments on commits Background: Given I sign in as a user And I own project "Shop" - Given I visit project commit page + And I visit project commit page @javascript - Scenario: I comment commit + Scenario: I can comment on a commit Given I leave a comment like "XML attached" - Then I should see comment "XML attached" + Then I should see a comment saying "XML attached" + + @javascript + Scenario: I can't cancel the main form + Then I should not see the cancel comment button + + @javascript + Scenario: I can't preview without text + Given I haven't written any comment text + Then I should not see the comment preview button + + @javascript + Scenario: I can preview with text + Given I write a comment like "Nice" + Then I should see the comment preview button + + @javascript + Scenario: I preview a comment + Given I preview a comment text like "Bug fixed :smile:" + Then I should see the comment preview + And I should not see the comment text field + + @javascript + Scenario: I can edit after preview + Given I preview a comment text like "Bug fixed :smile:" + Then I should see the comment edit button + + @javascript + Scenario: I have a reset form after posting from preview + Given I preview a comment text like "Bug fixed :smile:" + And I submit the comment + Then I should see an empty comment text field + And I should not see the comment preview + + @javascript + Scenario: I can delete a comment + Given I leave a comment like "XML attached" + And I delete a comment + Then I should not see a comment saying "XML attached" diff --git a/features/steps/project/comments_on_commits.rb b/features/steps/project/comments_on_commits.rb new file mode 100644 index 00000000000..56bb12a8209 --- /dev/null +++ b/features/steps/project/comments_on_commits.rb @@ -0,0 +1,6 @@ +class CommentsOnCommits < Spinach::FeatureSteps + include SharedAuthentication + include SharedNote + include SharedPaths + include SharedProject +end diff --git a/features/steps/project/project_comment_commit.rb b/features/steps/project/project_comment_commit.rb deleted file mode 100644 index cb8385e1ce5..00000000000 --- a/features/steps/project/project_comment_commit.rb +++ /dev/null @@ -1,6 +0,0 @@ -class ProjectCommentCommit < Spinach::FeatureSteps - include SharedAuthentication - include SharedProject - include SharedNote - include SharedPaths -end diff --git a/features/steps/shared/note.rb b/features/steps/shared/note.rb index 923e69b6b07..3d5441c40b0 100644 --- a/features/steps/shared/note.rb +++ b/features/steps/shared/note.rb @@ -1,18 +1,111 @@ module SharedNote include Spinach::DSL + Given 'I delete a comment' do + first(".js-note-delete").trigger("click") + end + + Given 'I haven\'t written any comment text' do + within(".js-main-target-form") do + fill_in "note[note]", with: "" + end + end + Given 'I leave a comment like "XML attached"' do - fill_in "note_note", :with => "XML attached" - click_button "Add Comment" + within(".js-main-target-form") do + fill_in "note[note]", with: "XML attached" + click_button "Add Comment" + end end - Then 'I should see comment "XML attached"' do - page.should have_content "XML attached" + Given 'I preview a comment text like "Bug fixed :smile:"' do + within(".js-main-target-form") do + fill_in "note[note]", with: "Bug fixed :smile:" + find(".js-note-preview-button").trigger("click") + end end + Given 'I submit the comment' do + within(".js-main-target-form") do + click_button "Add Comment" + end + end + + Given 'I write a comment like "Nice"' do + within(".js-main-target-form") do + fill_in "note[note]", with: "Nice" + end + end + + + + Then 'I should not see a comment saying "XML attached"' do + page.should_not have_css(".note") + end + + Then 'I should not see the cancel comment button' do + within(".js-main-target-form") do + should_not have_link("Cancel") + end + end + + Then 'I should not see the comment preview' do + within(".js-main-target-form") do + page.should have_css(".js-note-preview", visible: false) + end + end + + Then 'I should not see the comment preview button' do + within(".js-main-target-form") do + page.should have_css(".js-note-preview-button", visible: false) + end + end + + Then 'I should not see the comment text field' do + within(".js-main-target-form") do + page.should have_css(".js-note-text", visible: false) + end + end + + Then 'I should see a comment saying "XML attached"' do + within(".note") do + page.should have_content("XML attached") + end + end + + Then 'I should see an empty comment text field' do + within(".js-main-target-form") do + page.should have_field("note[note]", with: "") + end + end + + Then 'I should see the comment edit button' do + within(".js-main-target-form") do + page.should have_css(".js-note-edit-button", visible: true) + end + end + + Then 'I should see the comment preview' do + within(".js-main-target-form") do + page.should have_css(".js-note-preview", visible: true) + end + end + + Then 'I should see the comment preview button' do + within(".js-main-target-form") do + page.should have_css(".js-note-preview-button", visible: true) + end + end + + + + # Wall + Given 'I write new comment "my special test message"' do - fill_in "note_note", :with => "my special test message" - click_button "Add Comment" + within(".js-main-target-form") do + fill_in "note[note]", with: "my special test message" + click_button "Add Comment" + end end Then 'I should see project wall note "my special test message"' do diff --git a/spec/requests/notes_on_commits_spec.rb b/spec/requests/notes_on_commits_spec.rb index cba41c4df00..e301f9ac9bf 100644 --- a/spec/requests/notes_on_commits_spec.rb +++ b/spec/requests/notes_on_commits_spec.rb @@ -1,98 +1,12 @@ require 'spec_helper' -describe "On a commit", js: true do - let!(:project) { create(:project) } - let!(:commit) { project.commit("bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a") } - - before do - login_as :user - project.add_access(@user, :read, :write) - - visit project_commit_path(project, commit) - end - - subject { page } - - describe "the note form" do - # main target form creation - it { should have_css(".js-main-target-form", visible: true, count: 1) } - - # button initalization - it { within(".js-main-target-form") { should have_button("Add Comment") } } - it { within(".js-main-target-form") { should_not have_link("Cancel") } } - - # notifiactions - it { within(".js-main-target-form") { should have_unchecked_field("Project team") } } - it { within(".js-main-target-form") { should have_checked_field("Commit author") } } - - describe "without text" do - it { within(".js-main-target-form") { should have_css(".js-note-preview-button", visible: false) } } - end - - describe "with text" do - before do - within(".js-main-target-form") do - fill_in "note[note]", with: "This is awesome" - end - end - - it { within(".js-main-target-form") { should_not have_css(".js-comment-button[disabled]") } } - - it { within(".js-main-target-form") { should have_css(".js-note-preview-button", visible: true) } } - end - - describe "with preview" do - before do - within(".js-main-target-form") do - fill_in "note[note]", with: "This is awesome" - find(".js-note-preview-button").trigger("click") - end - end - - it { within(".js-main-target-form") { should have_css(".js-note-preview", text: "This is awesome", visible: true) } } - - it { within(".js-main-target-form") { should have_css(".js-note-preview-button", visible: false) } } - it { within(".js-main-target-form") { should have_css(".js-note-edit-button", visible: true) } } - end - end - - describe "when posting a note" do - before do - within(".js-main-target-form") do - fill_in "note[note]", with: "This is awsome!" - find(".js-note-preview-button").trigger("click") - click_button "Add Comment" - end - end - - # note added - it { within(".js-main-target-form") { should have_content("This is awsome!") } } - - # reset form - it { within(".js-main-target-form") { should have_no_field("note[note]", with: "This is awesome!") } } - - # return from preview - it { within(".js-main-target-form") { should have_css(".js-note-preview", visible: false) } } - it { within(".js-main-target-form") { should have_css(".js-note-text", visible: true) } } - - - it "should be removable" do - find(".js-note-delete").trigger("click") - - should_not have_css(".note") - end - end -end - - - describe "On a commit diff", js: true do let!(:project) { create(:project) } - let!(:commit) { project.commit("bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a") } + let!(:commit) { project.repository.commit("bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a") } before do login_as :user - project.add_access(@user, :read, :write) + project.team << [@user, :reporter] visit project_commit_path(project, commit) end -- cgit v1.2.1 From d28176b132bdc74055f31e2d62665d5d74ebacb4 Mon Sep 17 00:00:00 2001 From: Riyad Preukschas Date: Tue, 15 Jan 2013 00:11:35 +0100 Subject: Replace commit diff note request specs with spinach features --- .../project/commits/commit_diff_comments.feature | 91 ++++++++++++ features/steps/project/comments_on_commit_diffs.rb | 6 + features/steps/shared/diff_note.rb | 158 +++++++++++++++++++++ spec/requests/notes_on_commits_spec.rb | 137 ------------------ 4 files changed, 255 insertions(+), 137 deletions(-) create mode 100644 features/project/commits/commit_diff_comments.feature create mode 100644 features/steps/project/comments_on_commit_diffs.rb create mode 100644 features/steps/shared/diff_note.rb delete mode 100644 spec/requests/notes_on_commits_spec.rb diff --git a/features/project/commits/commit_diff_comments.feature b/features/project/commits/commit_diff_comments.feature new file mode 100644 index 00000000000..4323e8ce596 --- /dev/null +++ b/features/project/commits/commit_diff_comments.feature @@ -0,0 +1,91 @@ +Feature: Comments on commit diffs + Background: + Given I sign in as a user + And I own project "Shop" + And I visit project commit page + + @javascript + Scenario: I can access add diff comment buttons + Then I should see add a diff comment button + + @javascript + Scenario: I can comment on a commit diff + Given I leave a diff comment like "Typo, please fix" + Then I should see a diff comment saying "Typo, please fix" + + @javascript + Scenario: I get a temporary form for the first comment on a diff line + Given I open a diff comment form + Then I should see a temporary diff comment form + + @javascript + Scenario: I have a cancel button on the diff form + Given I open a diff comment form + Then I should see the cancel comment button + + @javascript + Scenario: I can cancel a diff form + Given I open a diff comment form + And I cancel the diff comment + Then I should not see the diff comment form + + @javascript + Scenario: I can't open a second form for a diff line + Given I open a diff comment form + And I open a diff comment form + Then I should only see one diff form + + @javascript + Scenario: I can have multiple forms + Given I open a diff comment form + And I write a diff comment like ":-1: I don't like this" + And I open another diff comment form + Then I should see a diff comment form with ":-1: I don't like this" + And I should see an empty diff comment form + + @javascript + Scenario: I can preview multiple forms separately + Given I preview a diff comment text like "Should fix it :smile:" + And I preview another diff comment text like "DRY this up" + Then I should see two separate previews + + @javascript + Scenario: I have a reply button in discussions + Given I leave a diff comment like "Typo, please fix" + Then I should see a discussion reply button + + @javascript + Scenario: I can't preview without text + Given I open a diff comment form + And I haven't written any diff comment text + Then I should not see the diff comment preview button + + @javascript + Scenario: I can preview with text + Given I open a diff comment form + And I write a diff comment like ":-1: I don't like this" + Then I should see the diff comment preview button + + @javascript + Scenario: I preview a diff comment + Given I preview a diff comment text like "Should fix it :smile:" + Then I should see the diff comment preview + And I should not see the diff comment text field + + @javascript + Scenario: I can edit after preview + Given I preview a diff comment text like "Should fix it :smile:" + Then I should see the diff comment edit button + + @javascript + Scenario: The form gets removed after posting + Given I preview a diff comment text like "Should fix it :smile:" + And I submit the diff comment + Then I should not see the diff comment form + And I should see a discussion reply button + + @javascript + Scenario: I can delete a discussion comment + Given I leave a diff comment like "Typo, please fix" + And I delete a diff comment + Then I should not see a diff comment saying "Typo, please fix" diff --git a/features/steps/project/comments_on_commit_diffs.rb b/features/steps/project/comments_on_commit_diffs.rb new file mode 100644 index 00000000000..fc397a4fa91 --- /dev/null +++ b/features/steps/project/comments_on_commit_diffs.rb @@ -0,0 +1,6 @@ +class CommentsOnCommitDiffs < Spinach::FeatureSteps + include SharedAuthentication + include SharedDiffNote + include SharedPaths + include SharedProject +end diff --git a/features/steps/shared/diff_note.rb b/features/steps/shared/diff_note.rb new file mode 100644 index 00000000000..36597e879bb --- /dev/null +++ b/features/steps/shared/diff_note.rb @@ -0,0 +1,158 @@ +module SharedDiffNote + include Spinach::DSL + + Given 'I cancel the diff comment' do + within(".diff_file") do + find(".js-close-discussion-note-form").trigger("click") + end + end + + Given 'I delete a diff comment' do + within(".diff_file") do + first(".js-note-delete").trigger("click") + end + end + + Given 'I haven\'t written any diff comment text' do + within(".diff_file") do + fill_in "note[note]", with: "" + end + end + + Given 'I leave a diff comment like "Typo, please fix"' do + find("#0_29_14.line_holder .js-add-diff-note-button").trigger("click") + within(".diff_file") do + fill_in "note[note]", with: "Typo, please fix" + #click_button("Add Comment") + find(".js-comment-button").trigger("click") + end + end + + Given 'I preview a diff comment text like "Should fix it :smile:"' do + find("#0_29_14.line_holder .js-add-diff-note-button").trigger("click") + within(".diff_file") do + fill_in "note[note]", with: "Should fix it :smile:" + find(".js-note-preview-button").trigger("click") + end + end + + Given 'I preview another diff comment text like "DRY this up"' do + find("#0_57_41.line_holder .js-add-diff-note-button").trigger("click") + within(".diff_file") do + fill_in "note[note]", with: "DRY this up" + find(".js-note-preview-button").trigger("click") + end + end + + Given 'I open a diff comment form' do + find("#0_29_14.line_holder .js-add-diff-note-button").trigger("click") + end + + Given 'I open another diff comment form' do + find("#0_57_41.line_holder .js-add-diff-note-button").trigger("click") + end + + Given 'I write a diff comment like ":-1: I don\'t like this"' do + within(".diff_file") do + fill_in "note[note]", with: ":-1: I don\'t like this" + end + end + + Given 'I submit the diff comment' do + within(".diff_file") do + click_button("Add Comment") + end + end + + + + Then 'I should not see the diff comment form' do + within(".diff_file") do + page.should_not have_css("form.new_note") + end + end + + Then 'I should not see the diff comment preview button' do + within(".diff_file") do + page.should have_css(".js-note-preview-button", visible: false) + end + end + + Then 'I should not see the diff comment text field' do + within(".diff_file") do + page.should have_css(".js-note-text", visible: false) + end + end + + Then 'I should only see one diff form' do + within(".diff_file") do + page.should have_css("form.new_note", count: 1) + end + end + + Then 'I should see a diff comment form with ":-1: I don\'t like this"' do + within(".diff_file") do + page.should have_field("note[note]", with: ":-1: I don\'t like this") + end + end + + Then 'I should see a diff comment saying "Typo, please fix"' do + within(".diff_file .note") do + page.should have_content("Typo, please fix") + end + end + + Then 'I should see a discussion reply button' do + within(".diff_file") do + page.should have_link("Reply") + end + end + + Then 'I should see a temporary diff comment form' do + within(".diff_file") do + page.should have_css(".js-temp-notes-holder form.new_note") + end + end + + Then 'I should see add a diff comment button' do + page.should have_css(".js-add-diff-note-button", visible: false) + end + + Then 'I should see an empty diff comment form' do + within(".diff_file") do + page.should have_field("note[note]", with: "") + end + end + + Then 'I should see the cancel comment button' do + within(".diff_file form") do + page.should have_css(".js-close-discussion-note-form", text: "Cancel") + end + end + + Then 'I should see the diff comment preview' do + within(".diff_file form") do + page.should have_css(".js-note-preview", visible: false) + end + end + + Then 'I should see the diff comment edit button' do + within(".diff_file") do + page.should have_css(".js-note-edit-button", visible: true) + end + end + + Then 'I should see the diff comment preview button' do + within(".diff_file") do + page.should have_css(".js-note-preview-button", visible: true) + end + end + + Then 'I should see two separate previews' do + within(".diff_file") do + page.should have_css(".js-note-preview", visible: true, count: 2) + page.should have_content("Should fix it") + page.should have_content("DRY this up") + end + end +end diff --git a/spec/requests/notes_on_commits_spec.rb b/spec/requests/notes_on_commits_spec.rb deleted file mode 100644 index e301f9ac9bf..00000000000 --- a/spec/requests/notes_on_commits_spec.rb +++ /dev/null @@ -1,137 +0,0 @@ -require 'spec_helper' - -describe "On a commit diff", js: true do - let!(:project) { create(:project) } - let!(:commit) { project.repository.commit("bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a") } - - before do - login_as :user - project.team << [@user, :reporter] - - visit project_commit_path(project, commit) - end - - subject { page } - - describe "when adding a note" do - before do - find("#0_185_185.line_holder .js-add-diff-note-button").trigger("click") - end - - describe "the notes holder" do - it { should have_css("#0_185_185.line_holder + .js-temp-notes-holder") } - - it { within(".js-temp-notes-holder") { should have_css(".new_note") } } - end - - describe "the note form" do - # set up hidden fields correctly - it { within(".js-temp-notes-holder") { find("#note_noteable_type").value.should == "Commit" } } - it { within(".js-temp-notes-holder") { find("#note_noteable_id").value.should == "" } } - it { within(".js-temp-notes-holder") { find("#note_commit_id").value.should == "bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a" } } - it { within(".js-temp-notes-holder") { find("#note_line_code").value.should == "0_185_185" } } - - # buttons - it { should have_button("Add Comment") } - it { should have_css(".js-close-discussion-note-form", text: "Cancel") } - - # notification options - it { should have_unchecked_field("Project team") } - it { should have_checked_field("Commit author") } - - it "shouldn't add a second form for same row" do - find("#0_185_185.line_holder .js-add-diff-note-button").trigger("click") - - should have_css("#0_185_185.line_holder + .js-temp-notes-holder form", count: 1) - end - - it "should be removed when canceled" do - find(".js-close-discussion-note-form").trigger("click") - - should have_no_css(".js-temp-notes-holder") - end - end - end - - describe "with muliple note forms" do - before do - find("#0_185_185.line_holder .js-add-diff-note-button").trigger("click") - find("#1_18_17.line_holder .js-add-diff-note-button").trigger("click") - end - - # has two line forms - it { should have_css(".js-temp-notes-holder", count: 2) } - - describe "previewing them separately" do - before do - # add two separate texts and trigger previews on both - within("#0_185_185.line_holder + .js-temp-notes-holder") do - fill_in "note[note]", with: "One comment on line 185" - find(".js-note-preview-button").trigger("click") - end - within("#1_18_17.line_holder + .js-temp-notes-holder") do - fill_in "note[note]", with: "Another comment on line 17" - find(".js-note-preview-button").trigger("click") - end - end - - # check if previews were rendered separately - it { within("#0_185_185.line_holder + .js-temp-notes-holder") { should have_css(".js-note-preview", text: "One comment on line 185") } } - it { within("#1_18_17.line_holder + .js-temp-notes-holder") { should have_css(".js-note-preview", text: "Another comment on line 17") } } - end - - describe "posting a note" do - before do - within("#1_18_17.line_holder + .js-temp-notes-holder") do - fill_in "note[note]", with: "Another comment on line 17" - click_button("Add Comment") - end - end - - # removed form after submit - it { should have_no_css("#1_18_17.line_holder + .js-temp-notes-holder") } - - # added discussion - it { should have_content("Another comment on line 17") } - it { should have_css("#1_18_17.line_holder + .notes_holder") } - it { should have_css("#1_18_17.line_holder + .notes_holder .note", count: 1) } - it { should have_link("Reply") } - - it "should remove last note of a discussion" do - within("#1_18_17.line_holder + .notes_holder") do - find(".js-note-delete").trigger("click") - end - - # removed whole discussion - should_not have_css(".note_holder") - should have_css("#1_18_17.line_holder + #1_18_18.line_holder") - end - end - end - - describe "when replying to a note" do - before do - # create first note - find("#0_184_184.line_holder .js-add-diff-note-button").trigger("click") - within("#0_184_184.line_holder + .js-temp-notes-holder") do - fill_in "note[note]", with: "One comment on line 184" - click_button("Add Comment") - end - # create second note - within("#0_184_184.line_holder + .notes_holder") do - find(".js-discussion-reply-button").trigger("click") - fill_in "note[note]", with: "An additional comment in reply" - click_button("Add Comment") - end - end - - # inserted note - it { should have_content("An additional comment in reply") } - it { within("#0_184_184.line_holder + .notes_holder") { should have_css(".note", count: 2) } } - - # removed form after reply - it { within("#0_184_184.line_holder + .notes_holder") { should have_no_css("form") } } - it { within("#0_184_184.line_holder + .notes_holder") { should have_link("Reply") } } - end -end - \ No newline at end of file -- cgit v1.2.1 From f598cc789789bcde01e3c703d9149204247c0a46 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 15 Jan 2013 11:12:17 +0200 Subject: change logic on line_code --- app/assets/javascripts/notes.js | 4 ++++ app/assets/stylesheets/sections/notes.scss | 11 ++++++++--- app/helpers/commits_helper.rb | 10 ++++++---- app/helpers/notes_helper.rb | 2 +- app/models/note.rb | 14 ++++++++++---- app/views/commits/_text_diff.html.haml | 2 +- app/views/notes/_discussion.html.haml | 24 ++++++++++++++++++++---- app/views/notes/_discussion_diff.html.haml | 2 +- app/views/notes/_note.html.haml | 6 +++--- 9 files changed, 54 insertions(+), 21 deletions(-) diff --git a/app/assets/javascripts/notes.js b/app/assets/javascripts/notes.js index 1eac462172b..8a7e08dd0e8 100644 --- a/app/assets/javascripts/notes.js +++ b/app/assets/javascripts/notes.js @@ -71,6 +71,10 @@ var NoteList = { $(document).on("click", ".js-choose-note-attachment-button", NoteList.chooseNoteAttachment); + + $(document).on("click", + ".js-show-outdated-discussion", + function(e) { $(this).next('.outdated-discussion').show(); e.preventDefault() }); }, diff --git a/app/assets/stylesheets/sections/notes.scss b/app/assets/stylesheets/sections/notes.scss index 93ad0d45037..3a1b650664f 100644 --- a/app/assets/stylesheets/sections/notes.scss +++ b/app/assets/stylesheets/sections/notes.scss @@ -79,7 +79,7 @@ ul.notes { margin-top: 3px; } .attachment { - font-size: 16px; + font-size: 14px; margin-top: -20px; .icon-attachment { @@ -92,7 +92,6 @@ ul.notes { } .note-body { margin-left: 45px; - padding-top: 5px; } .note-header { padding-bottom: 5px; @@ -284,7 +283,7 @@ ul.notes { font-size: 24px; padding: 4px; position: absolute; - right: 0; + right: 10px; } .note_preview { background: #f5f5f5; @@ -307,3 +306,9 @@ ul.notes { .notes-busy { margin: 18px; } + +.note-image-attach { + @extend .span4; + @extend .thumbnail; + margin-left: 45px; +} diff --git a/app/helpers/commits_helper.rb b/app/helpers/commits_helper.rb index 8fc637a2bf6..4b5d8bd96a6 100644 --- a/app/helpers/commits_helper.rb +++ b/app/helpers/commits_helper.rb @@ -9,11 +9,13 @@ module CommitsHelper end end - def build_line_anchor(index, line_new, line_old) - "#{index}_#{line_old}_#{line_new}" + def build_line_anchor(diff, line_new, line_old) + "#{hexdigest(diff.new_path)}_#{line_old}_#{line_new}" end - def each_diff_line(diff_arr, index) + def each_diff_line(diff, index) + diff_arr = diff.diff.lines.to_a + line_old = 1 line_new = 1 type = nil @@ -39,7 +41,7 @@ module CommitsHelper next else type = identification_type(line) - line_code = build_line_anchor(index, line_new, line_old) + line_code = build_line_anchor(diff, line_new, line_old) yield(full_line, type, line_code, line_new, line_old) end diff --git a/app/helpers/notes_helper.rb b/app/helpers/notes_helper.rb index fd920e23c19..7a0ed251aa8 100644 --- a/app/helpers/notes_helper.rb +++ b/app/helpers/notes_helper.rb @@ -17,7 +17,7 @@ module NotesHelper end def link_to_merge_request_diff_line_note(note) - if note.for_merge_request_diff_line? + if note.for_merge_request_diff_line? and note.diff link_to "#{note.diff_file_name}:L#{note.diff_new_line}", diffs_project_merge_request_path(note.project, note.noteable_id, anchor: note.line_code) end end diff --git a/app/models/note.rb b/app/models/note.rb index 3ad03cc601b..ded126b4bf1 100644 --- a/app/models/note.rb +++ b/app/models/note.rb @@ -33,7 +33,7 @@ class Note < ActiveRecord::Base delegate :name, :email, to: :author, prefix: true validates :note, :project, presence: true - validates :line_code, format: { with: /\A\d+_\d+_\d+\Z/ }, allow_blank: true + validates :line_code, format: { with: /\A[a-z0-9]+_\d+_\d+\Z/ }, allow_blank: true validates :attachment, file_size: { maximum: 10.megabytes.to_i } validates :noteable_id, presence: true, if: ->(n) { n.noteable_type.present? && n.noteable_type != 'Commit' } @@ -69,11 +69,17 @@ class Note < ActiveRecord::Base end def diff - noteable.diffs[diff_file_index] + if noteable.diffs.present? + noteable.diffs.select do |d| + if d.b_path + Digest::SHA1.hexdigest(d.b_path) == diff_file_index + end + end.first + end end def diff_file_index - line_code.split('_')[0].to_i + line_code.split('_')[0] end def diff_file_name @@ -85,7 +91,7 @@ class Note < ActiveRecord::Base end def discussion_id - @discussion_id ||= [:discussion, noteable_type.underscore, noteable_id, line_code].join("-").to_sym + @discussion_id ||= [:discussion, noteable_type.try(:underscore), noteable_id, line_code].join("-").to_sym end # Returns true if this is a downvote note, diff --git a/app/views/commits/_text_diff.html.haml b/app/views/commits/_text_diff.html.haml index ce07b87d548..8afad96bde2 100644 --- a/app/views/commits/_text_diff.html.haml +++ b/app/views/commits/_text_diff.html.haml @@ -3,7 +3,7 @@ %a.supp_diff_link Diff suppressed. Click to show %table{class: "#{'hide' if too_big}"} - - each_diff_line(diff.diff.lines.to_a, index) do |line, type, line_code, line_new, line_old| + - each_diff_line(diff, index) do |line, type, line_code, line_new, line_old| %tr.line_holder{ id: line_code } - if type == "match" %td.old_line= "..." diff --git a/app/views/notes/_discussion.html.haml b/app/views/notes/_discussion.html.haml index 031f4477ce3..093775f0d88 100644 --- a/app/views/notes/_discussion.html.haml +++ b/app/views/notes/_discussion.html.haml @@ -12,8 +12,15 @@ %div = link_to note.author_name, project_team_member_path(@project, @project.team_member_by_id(note.author)), class: "note-author" - if note.for_merge_request? - started a discussion on this merge request diff - = link_to_merge_request_diff_line_note(note) + - if note.diff + started a discussion on this merge request diff + = link_to_merge_request_diff_line_note(note) + - else + started + %strong + %i.icon-remove + outdated + discussion on this merge request diff - elsif note.for_commit? started a discussion on commit #{link_to note.noteable.short_id, project_commit_path(@project, note.noteable)} @@ -29,8 +36,17 @@ ago .discussion-body - if note.for_diff_line? - .content - .diff_file= render "notes/discussion_diff", discussion_notes: discussion_notes, note: note + - if note.diff + .content + .diff_file= render "notes/discussion_diff", discussion_notes: discussion_notes, note: note + - else + = link_to 'show outdated discussion', '#', class: 'js-show-outdated-discussion' + %div.hide.outdated-discussion + .content + .notes{ rel: discussion_notes.first.discussion_id } + = render discussion_notes + + - else .content .notes{ rel: discussion_notes.first.discussion_id } diff --git a/app/views/notes/_discussion_diff.html.haml b/app/views/notes/_discussion_diff.html.haml index 78f06f78f69..93ab59c72c5 100644 --- a/app/views/notes/_discussion_diff.html.haml +++ b/app/views/notes/_discussion_diff.html.haml @@ -9,7 +9,7 @@ %br/ .diff_file_content %table - - each_diff_line(diff.diff.lines.to_a, note.diff_file_index) do |line, type, line_code, line_new, line_old| + - each_diff_line(diff, note.diff_file_index) do |line, type, line_code, line_new, line_old| %tr.line_holder{ id: line_code } - if type == "match" %td.old_line= "..." diff --git a/app/views/notes/_note.html.haml b/app/views/notes/_note.html.haml index 6f7eea9827f..dd5d7c1ba8c 100644 --- a/app/views/notes/_note.html.haml +++ b/app/views/notes/_note.html.haml @@ -6,8 +6,8 @@ Link here   - if(note.author_id == current_user.id) || can?(current_user, :admin_note, @project) - = link_to project_note_path(@project, note), title: "Remove comment", method: :delete, confirm: 'Are you sure?', remote: true, class: "danger js-note-delete" do - %i.icon-remove-circle + = link_to project_note_path(@project, note), title: "Remove comment", method: :delete, confirm: 'Are you sure you want to remove comment?', remote: true, class: "danger js-note-delete" do + %i.icon-trash.cred = image_tag gravatar_icon(note.author.email), class: "avatar s32" = link_to note.author_name, project_team_member_path(@project, @project.team_member_by_id(note.author)), class: "note-author" %span.note-last-update @@ -29,7 +29,7 @@ = markdown(note.note) - if note.attachment.url - if note.attachment.image? - = image_tag note.attachment.url, class: 'thumbnail span4' + = image_tag note.attachment.url, class: 'note-image-attach' .attachment.right = link_to note.attachment.url, target: "_blank" do %i.icon-attachment -- cgit v1.2.1 From ac983319d3dca597d9a1dcfa46f6acc6ebcfa07a Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 15 Jan 2013 12:42:54 +0200 Subject: fixing some test --- features/steps/project/project_merge_requests.rb | 1 + features/steps/shared/diff_note.rb | 10 ++-- spec/requests/notes_on_merge_requests_spec.rb | 60 ++++++++++++------------ spec/requests/notes_on_wall_spec.rb | 3 +- 4 files changed, 36 insertions(+), 38 deletions(-) diff --git a/features/steps/project/project_merge_requests.rb b/features/steps/project/project_merge_requests.rb index f5b51737c8c..5d5ad4490de 100644 --- a/features/steps/project/project_merge_requests.rb +++ b/features/steps/project/project_merge_requests.rb @@ -110,6 +110,7 @@ class ProjectMergeRequests < Spinach::FeatureSteps end And 'I leave a comment like "Line is wrong" on line 185 of the first file' do + save_and_open_page within(:xpath, "//div[@class='diff_file'][1]") do click_link "add-diff-line-note-0_185_185" end diff --git a/features/steps/shared/diff_note.rb b/features/steps/shared/diff_note.rb index 36597e879bb..431ef022d0b 100644 --- a/features/steps/shared/diff_note.rb +++ b/features/steps/shared/diff_note.rb @@ -20,7 +20,7 @@ module SharedDiffNote end Given 'I leave a diff comment like "Typo, please fix"' do - find("#0_29_14.line_holder .js-add-diff-note-button").trigger("click") + find("#586fb7c4e1add2d4d24e27566ed7064680098646_29_14.line_holder .js-add-diff-note-button").trigger("click") within(".diff_file") do fill_in "note[note]", with: "Typo, please fix" #click_button("Add Comment") @@ -29,7 +29,7 @@ module SharedDiffNote end Given 'I preview a diff comment text like "Should fix it :smile:"' do - find("#0_29_14.line_holder .js-add-diff-note-button").trigger("click") + find("#586fb7c4e1add2d4d24e27566ed7064680098646_29_14.line_holder .js-add-diff-note-button").trigger("click") within(".diff_file") do fill_in "note[note]", with: "Should fix it :smile:" find(".js-note-preview-button").trigger("click") @@ -37,7 +37,7 @@ module SharedDiffNote end Given 'I preview another diff comment text like "DRY this up"' do - find("#0_57_41.line_holder .js-add-diff-note-button").trigger("click") + find("#586fb7c4e1add2d4d24e27566ed7064680098646_57_41.line_holder .js-add-diff-note-button").trigger("click") within(".diff_file") do fill_in "note[note]", with: "DRY this up" find(".js-note-preview-button").trigger("click") @@ -45,11 +45,11 @@ module SharedDiffNote end Given 'I open a diff comment form' do - find("#0_29_14.line_holder .js-add-diff-note-button").trigger("click") + find("#586fb7c4e1add2d4d24e27566ed7064680098646_29_14.line_holder .js-add-diff-note-button").trigger("click") end Given 'I open another diff comment form' do - find("#0_57_41.line_holder .js-add-diff-note-button").trigger("click") + find("#586fb7c4e1add2d4d24e27566ed7064680098646_57_41.line_holder .js-add-diff-note-button").trigger("click") end Given 'I write a diff comment like ":-1: I don\'t like this"' do diff --git a/spec/requests/notes_on_merge_requests_spec.rb b/spec/requests/notes_on_merge_requests_spec.rb index e10a7f2c2e2..8104582c920 100644 --- a/spec/requests/notes_on_merge_requests_spec.rb +++ b/spec/requests/notes_on_merge_requests_spec.rb @@ -6,7 +6,7 @@ describe "On a merge request", js: true do before do login_as :user - project.add_access(@user, :read, :write) + project.team << [@user, :master] visit project_merge_request_path(project, merge_request) end @@ -91,13 +91,11 @@ describe "On a merge request diff", js: true, focus: true do let!(:project) { create(:project) } let!(:merge_request) { create(:merge_request_with_diffs, project: project) } - before(:all) do + before do login_as :user - project.add_access(@user, :read, :write) - - visit project_merge_request_diff_path(project, merge_request) + project.team << [@user, :master] - save_and_open_page + visit diffs_project_merge_request_path(project, merge_request) click_link("Diff") end @@ -106,21 +104,21 @@ describe "On a merge request diff", js: true, focus: true do describe "when adding a note" do before do - find("#0_185_185.line_holder .js-add-diff-note-button").trigger("click") + find("#4735dfc552ad7bf15ca468adc3cad9d05b624490_185_185.line_holder .js-add-diff-note-button").trigger("click") end describe "the notes holder" do - it { should have_css("#0_185_185.line_holder + .js-temp-notes-holder") } + it { should have_css("#4735dfc552ad7bf15ca468adc3cad9d05b624490_185_185.line_holder + .js-temp-notes-holder") } it { within(".js-temp-notes-holder") { should have_css(".new_note") } } end describe "the note form" do # set up hidden fields correctly - it { within(".js-temp-notes-holder") { find("#note_noteable_type").value.should == "Commit" } } + it { within(".js-temp-notes-holder") { find("#note_noteable_type").value.should == "MergeRequest" } } it { within(".js-temp-notes-holder") { find("#note_noteable_id").value.should == "" } } it { within(".js-temp-notes-holder") { find("#note_commit_id").value.should == "bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a" } } - it { within(".js-temp-notes-holder") { find("#note_line_code").value.should == "0_185_185" } } + it { within(".js-temp-notes-holder") { find("#note_line_code").value.should == "4735dfc552ad7bf15ca468adc3cad9d05b624490_185_185" } } # buttons it { should have_button("Add Comment") } @@ -131,9 +129,9 @@ describe "On a merge request diff", js: true, focus: true do it { should have_checked_field("Commit author") } it "shouldn't add a second form for same row" do - find("#0_185_185.line_holder .js-add-diff-note-button").trigger("click") + find("#4735dfc552ad7bf15ca468adc3cad9d05b624490_185_185.line_holder .js-add-diff-note-button").trigger("click") - should have_css("#0_185_185.line_holder + .js-temp-notes-holder form", count: 1) + should have_css("#4735dfc552ad7bf15ca468adc3cad9d05b624490_185_185.line_holder + .js-temp-notes-holder form", count: 1) end it "should be removed when canceled" do @@ -146,8 +144,8 @@ describe "On a merge request diff", js: true, focus: true do describe "with muliple note forms" do before do - find("#0_185_185.line_holder .js-add-diff-note-button").trigger("click") - find("#1_18_17.line_holder .js-add-diff-note-button").trigger("click") + find("#4735dfc552ad7bf15ca468adc3cad9d05b624490_185_185.line_holder .js-add-diff-note-button").trigger("click") + find("#342e16cbbd482ac2047dc679b2749d248cc1428f_18_17.line_holder .js-add-diff-note-button").trigger("click") end # has two line forms @@ -156,46 +154,46 @@ describe "On a merge request diff", js: true, focus: true do describe "previewing them separately" do before do # add two separate texts and trigger previews on both - within("#0_185_185.line_holder + .js-temp-notes-holder") do + within("#4735dfc552ad7bf15ca468adc3cad9d05b624490_185_185.line_holder + .js-temp-notes-holder") do fill_in "note[note]", with: "One comment on line 185" find(".js-note-preview-button").trigger("click") end - within("#1_18_17.line_holder + .js-temp-notes-holder") do + within("#342e16cbbd482ac2047dc679b2749d248cc1428f_18_17.line_holder + .js-temp-notes-holder") do fill_in "note[note]", with: "Another comment on line 17" find(".js-note-preview-button").trigger("click") end end # check if previews were rendered separately - it { within("#0_185_185.line_holder + .js-temp-notes-holder") { should have_css(".js-note-preview", text: "One comment on line 185") } } - it { within("#1_18_17.line_holder + .js-temp-notes-holder") { should have_css(".js-note-preview", text: "Another comment on line 17") } } + it { within("#4735dfc552ad7bf15ca468adc3cad9d05b624490_185_185.line_holder + .js-temp-notes-holder") { should have_css(".js-note-preview", text: "One comment on line 185") } } + it { within("#342e16cbbd482ac2047dc679b2749d248cc1428f_18_17.line_holder + .js-temp-notes-holder") { should have_css(".js-note-preview", text: "Another comment on line 17") } } end describe "posting a note" do before do - within("#1_18_17.line_holder + .js-temp-notes-holder") do + within("#342e16cbbd482ac2047dc679b2749d248cc1428f_18_17.line_holder + .js-temp-notes-holder") do fill_in "note[note]", with: "Another comment on line 17" click_button("Add Comment") end end # removed form after submit - it { should have_no_css("#1_18_17.line_holder + .js-temp-notes-holder") } + it { should have_no_css("#342e16cbbd482ac2047dc679b2749d248cc1428f_18_17.line_holder + .js-temp-notes-holder") } # added discussion it { should have_content("Another comment on line 17") } - it { should have_css("#1_18_17.line_holder + .notes_holder") } - it { should have_css("#1_18_17.line_holder + .notes_holder .note", count: 1) } + it { should have_css("#342e16cbbd482ac2047dc679b2749d248cc1428f_18_17.line_holder + .notes_holder") } + it { should have_css("#342e16cbbd482ac2047dc679b2749d248cc1428f_18_17.line_holder + .notes_holder .note", count: 1) } it { should have_link("Reply") } it "should remove last note of a discussion" do - within("#1_18_17.line_holder + .notes_holder") do + within("#342e16cbbd482ac2047dc679b2749d248cc1428f_18_17.line_holder + .notes_holder") do find(".js-note-delete").trigger("click") end # removed whole discussion should_not have_css(".note_holder") - should have_css("#1_18_17.line_holder + #1_18_18.line_holder") + should have_css("#342e16cbbd482ac2047dc679b2749d248cc1428f_18_17.line_holder + #342e16cbbd482ac2047dc679b2749d248cc1428f_18_18.line_holder") end end end @@ -203,13 +201,13 @@ describe "On a merge request diff", js: true, focus: true do describe "when replying to a note" do before do # create first note - find("#0_184_184.line_holder .js-add-diff-note-button").trigger("click") - within("#0_184_184.line_holder + .js-temp-notes-holder") do + find("#4735dfc552ad7bf15ca468adc3cad9d05b624490_184_184.line_holder .js-add-diff-note-button").trigger("click") + within("#4735dfc552ad7bf15ca468adc3cad9d05b624490_184_184.line_holder + .js-temp-notes-holder") do fill_in "note[note]", with: "One comment on line 184" click_button("Add Comment") end # create second note - within("#0_184_184.line_holder + .notes_holder") do + within("#4735dfc552ad7bf15ca468adc3cad9d05b624490_184_184.line_holder + .notes_holder") do find(".js-discussion-reply-button").trigger("click") fill_in "note[note]", with: "An additional comment in reply" click_button("Add Comment") @@ -218,11 +216,11 @@ describe "On a merge request diff", js: true, focus: true do # inserted note it { should have_content("An additional comment in reply") } - it { within("#0_184_184.line_holder + .notes_holder") { should have_css(".note", count: 2) } } + it { within("#4735dfc552ad7bf15ca468adc3cad9d05b624490_184_184.line_holder + .notes_holder") { should have_css(".note", count: 2) } } # removed form after reply - it { within("#0_184_184.line_holder + .notes_holder") { should have_no_css("form") } } - it { within("#0_184_184.line_holder + .notes_holder") { should have_link("Reply") } } + it { within("#4735dfc552ad7bf15ca468adc3cad9d05b624490_184_184.line_holder + .notes_holder") { should have_no_css("form") } } + it { within("#4735dfc552ad7bf15ca468adc3cad9d05b624490_184_184.line_holder + .notes_holder") { should have_link("Reply") } } end end @@ -232,4 +230,4 @@ describe "On merge request discussion", js: true do describe "with merge request diff note" describe "with commit note" describe "with commit diff note" -end \ No newline at end of file +end diff --git a/spec/requests/notes_on_wall_spec.rb b/spec/requests/notes_on_wall_spec.rb index b42d293f9d6..c644603d3fa 100644 --- a/spec/requests/notes_on_wall_spec.rb +++ b/spec/requests/notes_on_wall_spec.rb @@ -6,8 +6,7 @@ describe "On the project wall", js: true do before do login_as :user - project.add_access(@user, :read, :write) - + project.team << [@user, :master] visit wall_project_path(project) end -- cgit v1.2.1