summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrandx <dmitriy.zaporozhets@gmail.com>2012-09-15 09:58:34 +0300
committerrandx <dmitriy.zaporozhets@gmail.com>2012-09-15 09:58:34 +0300
commit0546b9c65f33757dee6e7d0a6f85eb2bdb33453d (patch)
treea0a0d186ee46011d782b6819682ca780d33be60f
parenta82977c64843aa177498f1a715121ae6e38bc323 (diff)
parent348def03449f8f92fc1b568df7ad2fef40343587 (diff)
downloadgitlab-ce-0546b9c65f33757dee6e7d0a6f85eb2bdb33453d.tar.gz
Merge branch 'riyad-change-notes-order'
-rw-r--r--app/assets/javascripts/note.js182
-rw-r--r--app/assets/javascripts/notes.js251
-rw-r--r--app/assets/stylesheets/sections/notes.scss24
-rw-r--r--app/contexts/notes/load_context.rb33
-rw-r--r--app/helpers/notes_helper.rb9
-rw-r--r--app/models/note.rb2
-rw-r--r--app/models/project.rb4
-rw-r--r--app/models/wiki.rb1
-rw-r--r--app/views/commits/_text_file.html.haml9
-rw-r--r--app/views/commits/show.html.haml2
-rw-r--r--app/views/issues/show.html.haml2
-rw-r--r--app/views/merge_requests/_show.html.haml2
-rw-r--r--app/views/merge_requests/diffs.html.haml4
-rw-r--r--app/views/merge_requests/diffs.js.haml3
-rw-r--r--app/views/merge_requests/show.js.haml2
-rw-r--r--app/views/notes/_common_form.html.haml (renamed from app/views/notes/_form.html.haml)0
-rw-r--r--app/views/notes/_create_common_note.js.haml (renamed from app/views/notes/_create_common.js.haml)5
-rw-r--r--app/views/notes/_create_line.js.haml8
-rw-r--r--app/views/notes/_create_per_line_note.js.haml19
-rw-r--r--app/views/notes/_load.js.haml17
-rw-r--r--app/views/notes/_note.html.haml (renamed from app/views/notes/_show.html.haml)0
-rw-r--r--app/views/notes/_notes.html.haml15
-rw-r--r--app/views/notes/_notes_list.html.haml4
-rw-r--r--app/views/notes/_notes_with_form.html.haml11
-rw-r--r--app/views/notes/_per_line_note.html.haml5
-rw-r--r--app/views/notes/_per_line_note_link.html.haml1
-rw-r--r--app/views/notes/_per_line_notes_with_reply.html.haml3
-rw-r--r--app/views/notes/_per_line_reply_button.html.haml4
-rw-r--r--app/views/notes/_per_line_show.html.haml5
-rw-r--r--app/views/notes/_reply_button.html.haml4
-rw-r--r--app/views/notes/_reversed_notes_with_form.html.haml11
-rw-r--r--app/views/notes/create.js.haml4
-rw-r--r--app/views/notes/index.js.haml18
-rw-r--r--app/views/projects/wall.html.haml2
-rw-r--r--app/views/snippets/show.html.haml2
-rw-r--r--app/views/wikis/show.html.haml2
36 files changed, 397 insertions, 273 deletions
diff --git a/app/assets/javascripts/note.js b/app/assets/javascripts/note.js
deleted file mode 100644
index 79ab086bfa2..00000000000
--- a/app/assets/javascripts/note.js
+++ /dev/null
@@ -1,182 +0,0 @@
-var NoteList = {
-
- notes_path: null,
- target_params: null,
- target_id: 0,
- target_type: null,
- first_id: 0,
- last_id: 0,
- disable:false,
-
- init:
- function(tid, tt, path) {
- this.notes_path = path + ".js";
- this.target_id = tid;
- this.target_type = tt;
- this.target_params = "&target_type=" + this.target_type + "&target_id=" + this.target_id;
-
- // get notes
- this.getContent();
-
- // get new notes every n seconds
- this.initRefresh();
-
- $('.delete-note').live('ajax:success', function() {
- $(this).closest('li').fadeOut(); });
-
- $(".note-form-holder").live("ajax:before", function(){
- $(".submit_note").disable()
- })
-
- $(".note-form-holder").live("ajax:complete", function(){
- $(".submit_note").enable()
- })
-
- disableButtonIfEmptyField(".note-text", ".submit_note");
-
- $(".note-text").live("focus", function(){
- $(this).css("height", "80px");
- $('.note_advanced_opts').show();
- });
-
- $("#note_attachment").change(function(e){
- var val = $('.input-file').val();
- var filename = val.replace(/^.*[\\\/]/, '');
- $(".file_name").text(filename);
- });
-
- },
-
-
- /**
- * Load new notes to fresh list called 'new_notes_list':
- * - Replace 'new_notes_list' with new list every n seconds
- * - Append new notes to this list after submit
- */
-
- initRefresh:
- function() {
- // init timer
- var intNew = setInterval("NoteList.getNew()", 10000);
- },
-
- replace:
- function(html) {
- $("#new_notes_list").html(html);
- },
-
- prepend:
- function(id, html) {
- if(id != this.last_id) {
- $("#new_notes_list").prepend(html);
- }
- },
-
- getNew:
- function() {
- // refersh notes list
- $.ajax({
- type: "GET",
- url: this.notes_path,
- data: "last_id=" + this.last_id + this.target_params,
- dataType: "script"});
- },
-
- refresh:
- function() {
- // refersh notes list
- $.ajax({
- type: "GET",
- url: this.notes_path,
- data: "first_id=" + this.first_id + "&last_id=" + this.last_id + this.target_params,
- dataType: "script"});
- },
-
-
- /**
- * Init load of notes:
- * 1. Get content with ajax call
- * 2. Set content of notes list with loaded one
- */
-
-
- getContent:
- function() {
- $.ajax({
- type: "GET",
- url: this.notes_path,
- data: "?" + this.target_params,
- complete: function(){ $('.status').removeClass("loading")},
- beforeSend: function() { $('.status').addClass("loading") },
- dataType: "script"});
- },
-
- setContent:
- function(fid, lid, html) {
- this.last_id = lid;
- this.first_id = fid;
- $("#notes-list").html(html);
-
- // Init infinite scrolling
- this.initLoadMore();
- },
-
-
- /**
- * Paging for old notes when scroll to bottom:
- * 1. Init scroll events with 'initLoadMore'
- * 2. Load onlder notes with 'getOld' method
- * 3. append old notes to bottom of list with 'append'
- *
- */
- getOld:
- function() {
- $('.loading').show();
- $.ajax({
- type: "GET",
- url: this.notes_path,
- data: "first_id=" + this.first_id + this.target_params,
- complete: function(){ $('.status').removeClass("loading")},
- beforeSend: function() { $('.status').addClass("loading") },
- dataType: "script"});
- },
-
- append:
- function(id, html) {
- if(this.first_id == id) {
- this.disable = true;
- } else {
- this.first_id = id;
- $("#notes-list").append(html);
- }
- },
-
- initLoadMore:
- function() {
- $(document).endlessScroll({
- bottomPixels: 400,
- fireDelay: 1000,
- fireOnce:true,
- ceaseFire: function() {
- return NoteList.disable;
- },
- callback: function(i) {
- NoteList.getOld();
- }
- });
- }
-};
-
-var PerLineNotes = {
- init:
- function() {
- $(".line_note_link, .line_note_reply_link").live("click", function(e) {
- var form = $(".per_line_form");
- $(this).closest("tr").after(form);
- form.find("#note_line_code").val($(this).attr("line_code"));
- form.show();
- return false;
- });
- disableButtonIfEmptyField(".line-note-text", ".submit_inline_note");
- }
-}
diff --git a/app/assets/javascripts/notes.js b/app/assets/javascripts/notes.js
new file mode 100644
index 00000000000..81bb1d6d1b0
--- /dev/null
+++ b/app/assets/javascripts/notes.js
@@ -0,0 +1,251 @@
+var NoteList = {
+
+ notes_path: null,
+ target_params: null,
+ target_id: 0,
+ target_type: null,
+ top_id: 0,
+ bottom_id: 0,
+ 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").hasClass("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", ".delete-note", function() {
+ $(this).closest('li').fadeOut();
+ });
+
+ $(".note-form-holder").on("ajax:before", function(){
+ $(".submit_note").disable()
+ })
+
+ $(".note-form-holder").on("ajax:complete", function(){
+ $(".submit_note").enable()
+ })
+
+ disableButtonIfEmptyField(".note-text", ".submit_note");
+
+ $(".note-text").on("focus", function(){
+ $(this).css("height", "80px");
+ $('.note_advanced_opts').show();
+ });
+
+ $("#note_attachment").change(function(e){
+ var val = $('.input-file').val();
+ var filename = val.replace(/^.*[\\\/]/, '');
+ $(".file_name").text(filename);
+ });
+ },
+
+
+ /**
+ * Handle loading the initial set of notes.
+ * And set up loading more notes when scrolling to the bottom of the page.
+ */
+
+
+ /**
+ * Gets an inital set of notes.
+ */
+ 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"});
+ },
+
+ /**
+ * Called in response to getContent().
+ * 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;
+ $("#notes-list").html(html);
+
+ // init infinite scrolling
+ this.initLoadMore();
+
+ // init getting new notes
+ if (this.reversed) {
+ this.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.
+ *
+ * Set up refreshing only new notes after all notes have been loaded.
+ */
+
+
+ /**
+ * 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();
+ }
+ });
+ },
+
+ /**
+ * Gets an additional set of notes.
+ */
+ getMore:
+ function() {
+ // only load more notes if there are no "new" notes
+ $('.loading').show();
+ $.ajax({
+ type: "GET",
+ url: this.notes_path,
+ data: "loading_more=1&" + (this.reversed ? "before_id" : "after_id") + "=" + this.bottom_id + this.target_params,
+ 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(id, html) {
+ if(id != this.bottom_id) {
+ this.bottom_id = id;
+ $("#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;
+
+ // from now on only get new notes
+ if (!this.reversed) {
+ this.initRefreshNew();
+ }
+ },
+
+
+ /**
+ * Handle refreshing and adding of new notes.
+ *
+ * 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.
+ */
+
+
+ /**
+ * Initializes getting new notes every n seconds.
+ */
+ initRefreshNew:
+ function() {
+ setInterval("NoteList.getNew()", 10000);
+ },
+
+ /**
+ * Gets the new set of notes.
+ */
+ getNew:
+ function() {
+ $.ajax({
+ type: "GET",
+ url: this.notes_path,
+ data: "loading_new=1&after_id=" + (this.reversed ? this.top_id : this.bottom_id) + this.target_params,
+ dataType: "script"});
+ },
+
+ /**
+ * Called in response to getNew().
+ * Replaces the content of #new-notes-list with the given html.
+ */
+ replaceNewNotes:
+ function(html) {
+ $("#new-notes-list").html(html);
+ },
+
+ /**
+ * Adds a single note to #new-notes-list.
+ */
+ appendNewNote:
+ function(id, html) {
+ if (this.reversed) {
+ $("#new-notes-list").prepend(html);
+ } else {
+ $("#new-notes-list").append(html);
+ }
+ }
+};
+
+var PerLineNotes = {
+ init:
+ function() {
+ /**
+ * 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) {
+ var form = $(".per_line_form");
+ $(this).closest("tr").after(form);
+ form.find("#note_line_code").val($(this).data("lineCode"));
+ form.show();
+ return false;
+ });
+
+ 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", ".delete-note", 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.hasClass("line_holder") && trRpl.hasClass("reply")) {
+ trRpl.fadeOut(function() { $(this).remove(); });
+ }
+ });
+ }
+}
diff --git a/app/assets/stylesheets/sections/notes.scss b/app/assets/stylesheets/sections/notes.scss
index 6a965fa47b9..148807d6521 100644
--- a/app/assets/stylesheets/sections/notes.scss
+++ b/app/assets/stylesheets/sections/notes.scss
@@ -3,15 +3,18 @@
*
*/
#notes-list,
-#new_notes_list {
+#new-notes-list {
display:block;
list-style:none;
margin:0px;
padding:0px;
}
-#new_notes_list li:last-child{
- border-bottom:1px solid #aaa;
+#new-notes-list:not(.reversed) {
+ border-top:1px solid #aaa;
+}
+#new-notes-list.reversed {
+ border-bottom:1px solid #ccc;
}
.issue_notes,
@@ -48,7 +51,6 @@
.note {
padding: 8px 0;
- border-bottom: 1px solid #eee;
overflow: hidden;
display: block;
img {float: left; margin-right: 10px;}
@@ -70,6 +72,18 @@
.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;
+}
+
+.notes-status {
+ margin: 18px;
+}
p.notify_controls input{
@@ -213,7 +227,7 @@ td .line_note_link {
}
}
-.note-text {
+.note-text {
border: 1px solid #aaa;
box-shadow:none;
}
diff --git a/app/contexts/notes/load_context.rb b/app/contexts/notes/load_context.rb
index c89a7d19761..f92a780187d 100644
--- a/app/contexts/notes/load_context.rb
+++ b/app/contexts/notes/load_context.rb
@@ -3,30 +3,31 @@ module Notes
def execute
target_type = params[:target_type]
target_id = params[:target_id]
- first_id = params[:first_id]
- last_id = params[:last_id]
+ after_id = params[:after_id]
+ before_id = params[:before_id]
@notes = case target_type
- when "commit"
- then project.commit_notes(project.commit(target_id)).fresh.limit(20)
- when "snippet"
- then project.snippets.find(target_id).notes
- when "wall"
- then project.common_notes.order("created_at DESC").fresh.limit(50)
+ when "commit"
+ project.commit_notes(project.commit(target_id)).fresh.limit(20)
when "issue"
- then project.issues.find(target_id).notes.inc_author.order("created_at DESC").limit(20)
+ project.issues.find(target_id).notes.inc_author.fresh.limit(20)
when "merge_request"
- then project.merge_requests.find(target_id).notes.inc_author.order("created_at DESC").limit(20)
+ project.merge_requests.find(target_id).notes.inc_author.fresh.limit(20)
+ when "snippet"
+ project.snippets.find(target_id).notes.fresh
+ when "wall"
+ # this is the only case, where the order is DESC
+ project.common_notes.order("created_at DESC, id DESC").limit(50)
when "wiki"
- then project.wikis.reverse.map {|w| w.notes.fresh }.flatten[0..20]
+ project.wiki_notes.limit(20)
end
- @notes = if last_id
- @notes.where("id > ?", last_id)
- elsif first_id
- @notes.where("id < ?", first_id)
- else
+ @notes = if after_id
+ @notes.where("id > ?", after_id)
+ elsif before_id
+ @notes.where("id < ?", before_id)
+ else
@notes
end
end
diff --git a/app/helpers/notes_helper.rb b/app/helpers/notes_helper.rb
new file mode 100644
index 00000000000..28701661dc4
--- /dev/null
+++ b/app/helpers/notes_helper.rb
@@ -0,0 +1,9 @@
+module NotesHelper
+ 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 4c46c7dfffa..34edb94edca 100644
--- a/app/models/note.rb
+++ b/app/models/note.rb
@@ -36,7 +36,7 @@ class Note < ActiveRecord::Base
scope :today, where("created_at >= :date", date: Date.today)
scope :last_week, where("created_at >= :date", date: (Date.today - 7.days))
scope :since, lambda { |day| where("created_at >= :date", date: (day)) }
- scope :fresh, order("created_at DESC")
+ scope :fresh, order("created_at ASC, id ASC")
scope :inc_author_project, includes(:project, :author)
scope :inc_author, includes(:author)
diff --git a/app/models/project.rb b/app/models/project.rb
index 4de836c7b48..56d5d7910b9 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -171,6 +171,10 @@ class Project < ActiveRecord::Base
end
end
+ def wiki_notes
+ Note.where(noteable_id: wikis.map(&:id), noteable_type: 'Wiki', project_id: self.id)
+ end
+
def project_id
self.id
end
diff --git a/app/models/wiki.rb b/app/models/wiki.rb
index 3c4952cd291..ebb1ff49c7a 100644
--- a/app/models/wiki.rb
+++ b/app/models/wiki.rb
@@ -28,7 +28,6 @@ class Wiki < ActiveRecord::Base
end
new_wiki
end
-
end
end
# == Schema Information
diff --git a/app/views/commits/_text_file.html.haml b/app/views/commits/_text_file.html.haml
index 0f6210f2b5a..9f5b5345d5f 100644
--- a/app/views/commits/_text_file.html.haml
+++ b/app/views/commits/_text_file.html.haml
@@ -13,14 +13,11 @@
%td.old_line
= link_to raw(type == "new" ? "&nbsp;" : line_old), "##{line_code}", id: line_code
- if @comments_allowed
- = link_to "", "#", class: "line_note_link", "line_code" => line_code, title: "Add note for this line"
+ = render "notes/per_line_note_link", line_code: line_code
%td.new_line= link_to raw(type == "old" ? "&nbsp;" : line_new) , "##{line_code}", id: line_code
%td.line_content{class: "noteable_line #{type} #{line_code}", "line_code" => line_code}= raw "#{line} &nbsp;"
- if @comments_allowed
- - comments = @line_notes.select { |n| n.line_code == line_code }.sort_by(&:created_at).reverse
+ - comments = @line_notes.select { |n| n.line_code == line_code }.sort_by(&:created_at)
- unless comments.empty?
- - comments.each_with_index do |note, i|
- = render "notes/reply_button", line_code: line_code if i.zero?
- = render "notes/per_line_show", note: note
- - @line_notes.reject!{ |n| n == note }
+ = render "notes/per_line_notes_with_reply", notes: comments
diff --git a/app/views/commits/show.html.haml b/app/views/commits/show.html.haml
index e01f8ea5878..d12fff96835 100644
--- a/app/views/commits/show.html.haml
+++ b/app/views/commits/show.html.haml
@@ -1,6 +1,6 @@
= render "commits/commit_box"
= render "commits/diffs", diffs: @commit.diffs
-= render "notes/notes", tid: @commit.id, tt: "commit"
+= render "notes/notes_with_form", tid: @commit.id, tt: "commit"
= render "notes/per_line_form"
diff --git a/app/views/issues/show.html.haml b/app/views/issues/show.html.haml
index 9b1c72a3a12..0b72a820bb4 100644
--- a/app/views/issues/show.html.haml
+++ b/app/views/issues/show.html.haml
@@ -61,4 +61,4 @@
= markdown @issue.description
-.issue_notes#notes= render "notes/notes", tid: @issue.id, tt: "issue"
+.issue_notes#notes= render "notes/notes_with_form", tid: @issue.id, tt: "issue"
diff --git a/app/views/merge_requests/_show.html.haml b/app/views/merge_requests/_show.html.haml
index f1b3fa9fe98..40b72190199 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#notes{ class: (controller.action_name == 'show') ? "" : "hide" }
- = render("notes/notes", tid: @merge_request.id, tt: "merge_request")
+ = render("notes/notes_with_form", tid: @merge_request.id, tt: "merge_request")
.merge-request-diffs
= render "merge_requests/show/diffs" if @diffs
.status
diff --git a/app/views/merge_requests/diffs.html.haml b/app/views/merge_requests/diffs.html.haml
index 176b19bcbbb..a755491c42e 100644
--- a/app/views/merge_requests/diffs.html.haml
+++ b/app/views/merge_requests/diffs.html.haml
@@ -1,2 +1,6 @@
= render "show"
+:javascript
+ $(function(){
+ PerLineNotes.init();
+ });
diff --git a/app/views/merge_requests/diffs.js.haml b/app/views/merge_requests/diffs.js.haml
index b147e5be71c..98539985324 100644
--- a/app/views/merge_requests/diffs.js.haml
+++ b/app/views/merge_requests/diffs.js.haml
@@ -1,4 +1,7 @@
:plain
$(".merge-request-diffs").html("#{escape_javascript(render(partial: "merge_requests/show/diffs"))}");
+ $(function(){
+ PerLineNotes.init();
+ });
diff --git a/app/views/merge_requests/show.js.haml b/app/views/merge_requests/show.js.haml
index 7a27b166849..f44ccbb5127 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", tid: @merge_request.id, tt: "merge_request"))}");
+ $(".merge-request-notes").html("#{escape_javascript(render notes/notes_with_form", tid: @merge_request.id, tt: "merge_request")}");
diff --git a/app/views/notes/_form.html.haml b/app/views/notes/_common_form.html.haml
index 6d559cfc790..6d559cfc790 100644
--- a/app/views/notes/_form.html.haml
+++ b/app/views/notes/_common_form.html.haml
diff --git a/app/views/notes/_create_common.js.haml b/app/views/notes/_create_common_note.js.haml
index e80eccb1b4c..bbebc2478c5 100644
--- a/app/views/notes/_create_common.js.haml
+++ b/app/views/notes/_create_common_note.js.haml
@@ -5,8 +5,9 @@
$('.note-form-holder #preview-link').text('Preview');
$('.note-form-holder #preview-note').hide();
$('.note-form-holder').show();
- NoteList.prepend(#{note.id}, "#{escape_javascript(render partial: "notes/show", locals: {note: note})}");
+ NoteList.appendNewNote(#{note.id}, "#{escape_javascript(render "notes/note", note: note)}");
+
- else
:plain
- $(".note-form-holder").replaceWith("#{escape_javascript(render('form'))}");
+ $(".note-form-holder").replaceWith("#{escape_javascript(render 'form')}");
diff --git a/app/views/notes/_create_line.js.haml b/app/views/notes/_create_line.js.haml
deleted file mode 100644
index 662909f7967..00000000000
--- a/app/views/notes/_create_line.js.haml
+++ /dev/null
@@ -1,8 +0,0 @@
-- if note.valid?
- :plain
- $(".per_line_form").hide();
- $('.line-note-form-holder textarea').val("");
- $("a.line_note_reply_link[line_code='#{note.line_code}']").closest("tr").remove();
- var trEl = $(".#{note.line_code}").parent();
- trEl.after("#{escape_javascript(render partial: "notes/per_line_show", locals: {note: note})}");
- trEl.after("#{escape_javascript(render partial: "notes/reply_button", locals: {line_code: note.line_code})}");
diff --git a/app/views/notes/_create_per_line_note.js.haml b/app/views/notes/_create_per_line_note.js.haml
new file mode 100644
index 00000000000..180960e38e4
--- /dev/null
+++ b/app/views/notes/_create_per_line_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-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", line_code: note.line_code)}");
+ 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/_load.js.haml b/app/views/notes/_load.js.haml
deleted file mode 100644
index c16a699a1b7..00000000000
--- a/app/views/notes/_load.js.haml
+++ /dev/null
@@ -1,17 +0,0 @@
-- unless @notes.blank?
- - if params[:last_id]
- :plain
- NoteList.replace("#{escape_javascript(render(partial: 'notes/notes_list'))}");
-
- - elsif params[:first_id]
- :plain
- NoteList.append(#{@notes.last.id}, "#{escape_javascript(render(partial: 'notes/notes_list'))}");
-
- - else
- :plain
- NoteList.setContent(#{@notes.last.id}, #{@notes.first.id}, "#{escape_javascript(render(partial: 'notes/notes_list'))}");
-
-- else
- - if params[:first_id]
- :plain
- NoteList.append(#{params[:first_id]}, "");
diff --git a/app/views/notes/_show.html.haml b/app/views/notes/_note.html.haml
index 3412e4ebae5..3412e4ebae5 100644
--- a/app/views/notes/_show.html.haml
+++ b/app/views/notes/_note.html.haml
diff --git a/app/views/notes/_notes.html.haml b/app/views/notes/_notes.html.haml
index e692e746465..adb5dfcbf18 100644
--- a/app/views/notes/_notes.html.haml
+++ b/app/views/notes/_notes.html.haml
@@ -1,13 +1,4 @@
-- if can? current_user, :write_note, @project
- = render "notes/form"
-.clear
-%hr
-%ul#new_notes_list
-%ul#notes-list
-.status
+- @notes.each do |note|
+ - next unless note.author
+ = render "note", note: note
-
-:javascript
- $(function(){
- NoteList.init("#{tid}", "#{tt}", "#{project_notes_path(@project)}");
- });
diff --git a/app/views/notes/_notes_list.html.haml b/app/views/notes/_notes_list.html.haml
deleted file mode 100644
index 5673988d87d..00000000000
--- a/app/views/notes/_notes_list.html.haml
+++ /dev/null
@@ -1,4 +0,0 @@
-- @notes.each do |note|
- - next unless note.author
- = render partial: "notes/show", locals: {note: note}
-
diff --git a/app/views/notes/_notes_with_form.html.haml b/app/views/notes/_notes_with_form.html.haml
new file mode 100644
index 00000000000..53716c1d3f4
--- /dev/null
+++ b/app/views/notes/_notes_with_form.html.haml
@@ -0,0 +1,11 @@
+%ul#notes-list
+%ul#new-notes-list
+.notes-status
+
+- if can? current_user, :write_note, @project
+ = render "notes/common_form"
+
+:javascript
+ $(function(){
+ NoteList.init("#{tid}", "#{tt}", "#{project_notes_path(@project)}");
+ });
diff --git a/app/views/notes/_per_line_note.html.haml b/app/views/notes/_per_line_note.html.haml
new file mode 100644
index 00000000000..28bcd6e0c94
--- /dev/null
+++ b/app/views/notes/_per_line_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/_per_line_note_link.html.haml b/app/views/notes/_per_line_note_link.html.haml
new file mode 100644
index 00000000000..72b59a596a3
--- /dev/null
+++ b/app/views/notes/_per_line_note_link.html.haml
@@ -0,0 +1 @@
+= link_to "", "#", class: "line_note_link", data: { line_code: line_code }, title: "Add note for 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
new file mode 100644
index 00000000000..1bcfc41fe20
--- /dev/null
+++ b/app/views/notes/_per_line_notes_with_reply.html.haml
@@ -0,0 +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
diff --git a/app/views/notes/_per_line_reply_button.html.haml b/app/views/notes/_per_line_reply_button.html.haml
new file mode 100644
index 00000000000..42c737c75ae
--- /dev/null
+++ b/app/views/notes/_per_line_reply_button.html.haml
@@ -0,0 +1,4 @@
+%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"
diff --git a/app/views/notes/_per_line_show.html.haml b/app/views/notes/_per_line_show.html.haml
deleted file mode 100644
index cf1769c0517..00000000000
--- a/app/views/notes/_per_line_show.html.haml
+++ /dev/null
@@ -1,5 +0,0 @@
-%tr.line_notes_row
- %td{colspan: 3}
- %ul
- = render partial: "notes/show", locals: {note: note}
-
diff --git a/app/views/notes/_reply_button.html.haml b/app/views/notes/_reply_button.html.haml
deleted file mode 100644
index c981fb9fc72..00000000000
--- a/app/views/notes/_reply_button.html.haml
+++ /dev/null
@@ -1,4 +0,0 @@
-%tr.line_notes_row.reply
- %td{colspan: 3}
- %i.icon-comment
- = link_to "Reply", "#", class: "line_note_reply_link", "line_code" => line_code, title: "Add note for this line"
diff --git a/app/views/notes/_reversed_notes_with_form.html.haml b/app/views/notes/_reversed_notes_with_form.html.haml
new file mode 100644
index 00000000000..05f01847da4
--- /dev/null
+++ b/app/views/notes/_reversed_notes_with_form.html.haml
@@ -0,0 +1,11 @@
+- if can? current_user, :write_note, @project
+ = render "notes/common_form"
+
+%ul.reversed#new-notes-list
+%ul.reversed#notes-list
+.notes-status
+
+:javascript
+ $(function(){
+ NoteList.init("#{tid}", "#{tt}", "#{project_notes_path(@project)}");
+ }); \ No newline at end of file
diff --git a/app/views/notes/create.js.haml b/app/views/notes/create.js.haml
index 8f631f38f79..03866591c4f 100644
--- a/app/views/notes/create.js.haml
+++ b/app/views/notes/create.js.haml
@@ -1,7 +1,7 @@
- if @note.line_code
- = render "create_line", note: @note
+ = render "create_per_line_note", note: @note
- else
- = render "create_common", note: @note
+ = render "create_common_note", note: @note
-# Enable submit button
:plain
diff --git a/app/views/notes/index.js.haml b/app/views/notes/index.js.haml
index ee31c0b8d3c..3814dbd46a2 100644
--- a/app/views/notes/index.js.haml
+++ b/app/views/notes/index.js.haml
@@ -1 +1,17 @@
-= render "notes/load"
+- unless @notes.blank?
+ - if loading_more_notes?
+ :plain
+ NoteList.appendMoreNotes(#{@notes.last.id}, "#{escape_javascript(render 'notes/notes')}");
+
+ - elsif loading_new_notes?
+ :plain
+ NoteList.replaceNewNotes("#{escape_javascript(render 'notes/notes')}");
+
+ - else
+ :plain
+ NoteList.setContent(#{@notes.first.id}, #{@notes.last.id}, "#{escape_javascript(render 'notes/notes')}");
+
+- else
+ - if loading_more_notes?
+ :plain
+ NoteList.finishedLoadingMore();
diff --git a/app/views/projects/wall.html.haml b/app/views/projects/wall.html.haml
index 97765d7ac88..591a8cd06d4 100644
--- a/app/views/projects/wall.html.haml
+++ b/app/views/projects/wall.html.haml
@@ -1,2 +1,2 @@
%div.wall_page
- = render "notes/notes", tid: nil, tt: "wall"
+ = render "notes/reversed_notes_with_form", tid: nil, tt: "wall"
diff --git a/app/views/snippets/show.html.haml b/app/views/snippets/show.html.haml
index 0800b81d330..4188a9f198c 100644
--- a/app/views/snippets/show.html.haml
+++ b/app/views/snippets/show.html.haml
@@ -17,4 +17,4 @@
%div{class: current_user.dark_scheme ? "black" : ""}
= raw @snippet.colorize(options: { linenos: 'True'})
-= render "notes/notes", tid: @snippet.id, tt: "snippet"
+= render "notes/notes_with_form", tid: @snippet.id, tt: "snippet"
diff --git a/app/views/wikis/show.html.haml b/app/views/wikis/show.html.haml
index fc2352271d5..579ea1b3ad6 100644
--- a/app/views/wikis/show.html.haml
+++ b/app/views/wikis/show.html.haml
@@ -21,4 +21,4 @@
Delete this page
%hr
-.wiki_notes#notes= render "notes/notes", tid: @wiki.id, tt: "wiki"
+.wiki_notes#notes= render "notes/notes_with_form", tid: @wiki.id, tt: "wiki"