From 78f131c0514bc99f73b9c063fac3158ab2e51e17 Mon Sep 17 00:00:00 2001
From: blackst0ne <blackst0ne.ru@gmail.com>
Date: Sat, 3 Jun 2017 12:40:20 +1100
Subject: [PATCH] Fix duplication of commits header on commits page

---
 app/assets/javascripts/activities.js          |  5 ++-
 app/assets/javascripts/commits.js             | 37 +++++++++++++++++--
 app/assets/javascripts/pager.js               |  5 ++-
 app/views/projects/commits/_commits.html.haml |  7 +++-
 changelogs/unreleased/fix_commits_page.yml    |  4 ++
 spec/javascripts/commits_spec.js              | 26 +++++++++++++
 6 files changed, 75 insertions(+), 9 deletions(-)
 create mode 100644 changelogs/unreleased/fix_commits_page.yml

diff --git a/app/assets/javascripts/activities.js b/app/assets/javascripts/activities.js
index d816df831eb..5d060165f4b 100644
--- a/app/assets/javascripts/activities.js
+++ b/app/assets/javascripts/activities.js
@@ -5,7 +5,8 @@ import Cookies from 'js-cookie';
 
 class Activities {
   constructor() {
-    Pager.init(20, true, false, this.updateTooltips);
+    Pager.init(20, true, false, data => data, this.updateTooltips);
+
     $('.event-filter-link').on('click', (e) => {
       e.preventDefault();
       this.toggleFilter(e.currentTarget);
@@ -19,7 +20,7 @@ class Activities {
 
   reloadActivities() {
     $('.content_list').html('');
-    Pager.init(20, true, false, this.updateTooltips);
+    Pager.init(20, true, false, data => data, this.updateTooltips);
   }
 
   toggleFilter(sender) {
diff --git a/app/assets/javascripts/commits.js b/app/assets/javascripts/commits.js
index e3f9eaaf39c..2b0bf49cf92 100644
--- a/app/assets/javascripts/commits.js
+++ b/app/assets/javascripts/commits.js
@@ -7,6 +7,8 @@ window.CommitsList = (function() {
   CommitsList.timer = null;
 
   CommitsList.init = function(limit) {
+    this.$contentList = $('.content_list');
+
     $("body").on("click", ".day-commits-table li.commit", function(e) {
       if (e.target.nodeName !== "A") {
         location.href = $(this).attr("url");
@@ -14,9 +16,9 @@ window.CommitsList = (function() {
         return false;
       }
     });
-    Pager.init(limit, false, false, function() {
-      gl.utils.localTimeAgo($('.js-timeago'));
-    });
+
+    Pager.init(limit, false, false, this.processCommits);
+
     this.content = $("#commits-list");
     this.searchField = $("#commits-search");
     this.lastSearch = this.searchField.val();
@@ -62,5 +64,34 @@ window.CommitsList = (function() {
     });
   };
 
+  // Prepare loaded data.
+  CommitsList.processCommits = (data) => {
+    let processedData = data;
+    const $processedData = $(processedData);
+    const $commitsHeadersLast = CommitsList.$contentList.find('li.js-commit-header').last();
+    const lastShownDay = $commitsHeadersLast.data('day');
+    const $loadedCommitsHeadersFirst = $processedData.filter('li.js-commit-header').first();
+    const loadedShownDayFirst = $loadedCommitsHeadersFirst.data('day');
+    let commitsCount;
+
+    // If commits headers show the same date,
+    // remove the last header and change the previous one.
+    if (lastShownDay === loadedShownDayFirst) {
+      // Last shown commits count under the last commits header.
+      commitsCount = $commitsHeadersLast.nextUntil('li.js-commit-header').find('li.commit').length;
+
+      // Remove duplicate of commits header.
+      processedData = $processedData.not(`li.js-commit-header[data-day="${loadedShownDayFirst}"]`);
+
+      // Update commits count in the previous commits header.
+      commitsCount += Number($(processedData).nextUntil('li.js-commit-header').first().find('li.commit').length);
+      $commitsHeadersLast.find('span.commits-count').text(`${commitsCount} ${gl.text.pluralize('commit', commitsCount)}`);
+    }
+
+    gl.utils.localTimeAgo($processedData.find('.js-timeago'));
+
+    return processedData;
+  };
+
   return CommitsList;
 })();
diff --git a/app/assets/javascripts/pager.js b/app/assets/javascripts/pager.js
index 0ef20af9260..01110420cca 100644
--- a/app/assets/javascripts/pager.js
+++ b/app/assets/javascripts/pager.js
@@ -6,11 +6,12 @@ import '~/lib/utils/url_utility';
   const ENDLESS_SCROLL_FIRE_DELAY_MS = 1000;
 
   const Pager = {
-    init(limit = 0, preload = false, disable = false, callback = $.noop) {
+    init(limit = 0, preload = false, disable = false, prepareData = $.noop, callback = $.noop) {
       this.url = $('.content_list').data('href') || gl.utils.removeParams(['limit', 'offset']);
       this.limit = limit;
       this.offset = parseInt(gl.utils.getParameterByName('offset'), 10) || this.limit;
       this.disable = disable;
+      this.prepareData = prepareData;
       this.callback = callback;
       this.loading = $('.loading').first();
       if (preload) {
@@ -29,7 +30,7 @@ import '~/lib/utils/url_utility';
         dataType: 'json',
         error: () => this.loading.hide(),
         success: (data) => {
-          this.append(data.count, data.html);
+          this.append(data.count, this.prepareData(data.html));
           this.callback();
 
           // keep loading until we've filled the viewport height
diff --git a/app/views/projects/commits/_commits.html.haml b/app/views/projects/commits/_commits.html.haml
index 88c7d7bc44b..d3380c917e4 100644
--- a/app/views/projects/commits/_commits.html.haml
+++ b/app/views/projects/commits/_commits.html.haml
@@ -2,8 +2,11 @@
 - commits, hidden = limited_commits(@commits)
 
 - commits.chunk { |c| c.committed_date.in_time_zone.to_date }.each do |day, commits|
-  %li.commit-header #{day.strftime('%d %b, %Y')} #{pluralize(commits.count, 'commit')}
-  %li.commits-row
+  %li.commit-header.js-commit-header{ data: { day: day } }
+    %span.day= day.strftime('%d %b, %Y')
+    %span.commits-count= pluralize(commits.count, 'commit')
+
+  %li.commits-row{ data: { day: day } }
     %ul.content-list.commit-list
       = render commits, project: project, ref: ref
 
diff --git a/changelogs/unreleased/fix_commits_page.yml b/changelogs/unreleased/fix_commits_page.yml
new file mode 100644
index 00000000000..a2afaf6e626
--- /dev/null
+++ b/changelogs/unreleased/fix_commits_page.yml
@@ -0,0 +1,4 @@
+---
+title: Fix duplication of commits header on commits page
+merge_request: 11006
+author: @blackst0ne
diff --git a/spec/javascripts/commits_spec.js b/spec/javascripts/commits_spec.js
index 187db7485a5..44a4386b250 100644
--- a/spec/javascripts/commits_spec.js
+++ b/spec/javascripts/commits_spec.js
@@ -28,6 +28,32 @@ import '~/commits';
       expect(CommitsList).toBeDefined();
     });
 
+    describe('processCommits', () => {
+      it('should join commit headers', () => {
+        CommitsList.$contentList = $(`
+          <div>
+            <li class="commit-header" data-day="2016-09-20">
+              <span class="day">20 Sep, 2016</span>
+              <span class="commits-count">1 commit</span>
+            </li>
+            <li class="commit"></li>
+          </div>
+        `);
+
+        const data = `
+          <li class="commit-header" data-day="2016-09-20">
+            <span class="day">20 Sep, 2016</span>
+            <span class="commits-count">1 commit</span>
+          </li>
+          <li class="commit"></li>
+        `;
+
+        // The last commit header should be removed
+        // since the previous one has the same data-day value.
+        expect(CommitsList.processCommits(data).find('li.commit-header').length).toBe(0);
+      });
+    });
+
     describe('on entering input', () => {
       let ajaxSpy;
 
-- 
2.30.9