From 171ece8f8b238cea385cbc19441a44160d4d3e18 Mon Sep 17 00:00:00 2001 From: Mike Greiling Date: Sun, 20 Nov 2016 01:27:03 -0600 Subject: [PATCH 1/9] rename activities.js to activities.js.es6 --- app/assets/javascripts/{activities.js => activities.js.es6} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename app/assets/javascripts/{activities.js => activities.js.es6} (100%) diff --git a/app/assets/javascripts/activities.js b/app/assets/javascripts/activities.js.es6 similarity index 100% rename from app/assets/javascripts/activities.js rename to app/assets/javascripts/activities.js.es6 From ed88515d56f72ba9f77cac2a4dca121fd34f622f Mon Sep 17 00:00:00 2001 From: Mike Greiling Date: Sat, 19 Nov 2016 23:52:53 -0600 Subject: [PATCH 2/9] convert activities.js to es6 class syntax --- app/assets/javascripts/activities.js.es6 | 52 ++++++++++++------------ app/assets/javascripts/dispatcher.js.es6 | 6 +-- app/assets/javascripts/user_tabs.js.es6 | 2 +- app/views/projects/_activity.html.haml | 2 +- spec/javascripts/activities_spec.js.es6 | 2 +- 5 files changed, 31 insertions(+), 33 deletions(-) diff --git a/app/assets/javascripts/activities.js.es6 b/app/assets/javascripts/activities.js.es6 index 906a1a69d93..da8a4a8f3a2 100644 --- a/app/assets/javascripts/activities.js.es6 +++ b/app/assets/javascripts/activities.js.es6 @@ -1,37 +1,35 @@ -/* eslint-disable func-names, space-before-function-paren, wrap-iife, no-undef, quotes, no-var, padded-blocks, max-len */ -(function() { - this.Activities = (function() { - function Activities() { +/* eslint-disable no-param-reassign, class-methods-use-this */ +/* global Pager, Cookies */ + +((global) => { + class Activities { + constructor() { Pager.init(20, true, false, this.updateTooltips); - $(".event-filter-link").on("click", (function(_this) { - return function(event) { - event.preventDefault(); - _this.toggleFilter($(event.currentTarget)); - return _this.reloadActivities(); - }; - })(this)); + $('.event-filter-link').on('click', (event) => { + event.preventDefault(); + this.toggleFilter($(event.currentTarget)); + this.reloadActivities(); + }); } - Activities.prototype.updateTooltips = function() { + updateTooltips() { gl.utils.localTimeAgo($('.js-timeago', '.content_list')); - }; + } - Activities.prototype.reloadActivities = function() { - $(".content_list").html(''); + reloadActivities() { + $('.content_list').html(''); Pager.init(20, true, false, this.updateTooltips); - }; + } - Activities.prototype.toggleFilter = function(sender) { - var filter = sender.attr("id").split("_")[0]; + toggleFilter(sender) { + const filter = sender.attr('id').split('_')[0]; - $('.event-filter .active').removeClass("active"); - Cookies.set("event_filter", filter); + $('.event-filter .active').removeClass('active'); + Cookies.set('event_filter', filter); - sender.closest('li').toggleClass("active"); - }; + sender.closest('li').toggleClass('active'); + } + } - return Activities; - - })(); - -}).call(this); + global.Activities = Activities; +})(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/dispatcher.js.es6 b/app/assets/javascripts/dispatcher.js.es6 index 756a24cc0fc..ab4858dca32 100644 --- a/app/assets/javascripts/dispatcher.js.es6 +++ b/app/assets/javascripts/dispatcher.js.es6 @@ -110,10 +110,10 @@ Issuable.init(); break; case 'dashboard:activity': - new Activities(); + new gl.Activities(); break; case 'dashboard:projects:starred': - new Activities(); + new gl.Activities(); break; case 'projects:commit:show': new Commit(); @@ -139,7 +139,7 @@ new gl.Pipelines(); break; case 'groups:activity': - new Activities(); + new gl.Activities(); break; case 'groups:show': shortcut_handler = new ShortcutsNavigation(); diff --git a/app/assets/javascripts/user_tabs.js.es6 b/app/assets/javascripts/user_tabs.js.es6 index 2b310da319c..5a625611987 100644 --- a/app/assets/javascripts/user_tabs.js.es6 +++ b/app/assets/javascripts/user_tabs.js.es6 @@ -134,7 +134,7 @@ content on the Users#show page. } const $calendarWrap = this.$parentEl.find('.user-calendar'); $calendarWrap.load($calendarWrap.data('href')); - new Activities(); + new gl.Activities(); return this.loaded['activity'] = true; } diff --git a/app/views/projects/_activity.html.haml b/app/views/projects/_activity.html.haml index d011e51e696..4f15f2997fb 100644 --- a/app/views/projects/_activity.html.haml +++ b/app/views/projects/_activity.html.haml @@ -13,7 +13,7 @@ = spinner :javascript - var activity = new Activities(); + var activity = new gl.Activities(); $(document).on('page:restore', function (event) { activity.reloadActivities() }) diff --git a/spec/javascripts/activities_spec.js.es6 b/spec/javascripts/activities_spec.js.es6 index 9d855ef1060..8640cd44085 100644 --- a/spec/javascripts/activities_spec.js.es6 +++ b/spec/javascripts/activities_spec.js.es6 @@ -35,7 +35,7 @@ describe('Activities', () => { beforeEach(() => { fixture.load(fixtureTemplate); - new Activities(); + new gl.Activities(); }); for(let i = 0; i < filters.length; i++) { From 23a8b6873b2c88dcc9e79650aa2ff66bfcc31060 Mon Sep 17 00:00:00 2001 From: Mike Greiling Date: Sun, 20 Nov 2016 01:29:33 -0600 Subject: [PATCH 3/9] rename pager.js to pager.js.es6 --- app/assets/javascripts/{pager.js => pager.js.es6} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename app/assets/javascripts/{pager.js => pager.js.es6} (100%) diff --git a/app/assets/javascripts/pager.js b/app/assets/javascripts/pager.js.es6 similarity index 100% rename from app/assets/javascripts/pager.js rename to app/assets/javascripts/pager.js.es6 From 324482659a6fe463afb1547a96ecd2f61570a60e Mon Sep 17 00:00:00 2001 From: Mike Greiling Date: Sun, 20 Nov 2016 00:11:30 -0600 Subject: [PATCH 4/9] convert pager.js to es6 syntax --- app/assets/javascripts/pager.js.es6 | 64 +++++++++++++---------------- 1 file changed, 28 insertions(+), 36 deletions(-) diff --git a/app/assets/javascripts/pager.js.es6 b/app/assets/javascripts/pager.js.es6 index d22d2d9dbae..25033ea659f 100644 --- a/app/assets/javascripts/pager.js.es6 +++ b/app/assets/javascripts/pager.js.es6 @@ -1,7 +1,6 @@ -/* eslint-disable func-names, space-before-function-paren, object-shorthand, quotes, no-undef, prefer-template, wrap-iife, comma-dangle, no-return-assign, no-else-return, consistent-return, no-unused-vars, padded-blocks, max-len */ -(function() { - this.Pager = { - init: function(limit, preload, disable, callback) { +(() => { + const Pager = { + init(limit, preload, disable, callback) { this.limit = limit != null ? limit : 0; this.disable = disable != null ? disable : false; this.callback = callback != null ? callback : $.noop; @@ -12,53 +11,46 @@ } else { this.offset = this.limit; } - return this.initLoadMore(); + this.initLoadMore(); }, - getOld: function() { + getOld() { this.loading.show(); - return $.ajax({ - type: "GET", - url: $(".content_list").data('href') || location.href, - data: "limit=" + this.limit + "&offset=" + this.offset, - complete: (function(_this) { - return function() { - return _this.loading.hide(); - }; - })(this), - success: function(data) { + $.ajax({ + type: 'GET', + url: $('.content_list').data('href') || window.location.href, + data: `limit=${this.limit}&offset=${this.offset}`, + complete: () => this.loading.hide(), + success: (data) => { Pager.append(data.count, data.html); - return Pager.callback(); + Pager.callback(); }, - dataType: "json" + dataType: 'json', }); }, - append: function(count, html) { - $(".content_list").append(html); + append(count, html) { + $('.content_list').append(html); if (count > 0) { - return this.offset += count; + this.offset += count; } else { - return this.disable = true; + this.disable = true; } }, - initLoadMore: function() { + initLoadMore() { $(document).unbind('scroll'); - return $(document).endlessScroll({ + $(document).endlessScroll({ bottomPixels: 400, fireDelay: 1000, fireOnce: true, - ceaseFire: function() { - return Pager.disable; + ceaseFire: () => Pager.disable !== true, + callback: () => { + if (!this.loading.is(':visible')) { + this.loading.show(); + Pager.getOld(); + } }, - callback: (function(_this) { - return function(i) { - if (!_this.loading.is(':visible')) { - _this.loading.show(); - return Pager.getOld(); - } - }; - })(this) }); - } + }, }; -}).call(this); + window.Pager = Pager; +})(); From 283bca3a2e06a2326a71ad4fcbf663da09cd0982 Mon Sep 17 00:00:00 2001 From: Mike Greiling Date: Sun, 20 Nov 2016 00:23:12 -0600 Subject: [PATCH 5/9] use param defaults and add spacing for readability --- app/assets/javascripts/pager.js.es6 | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/app/assets/javascripts/pager.js.es6 b/app/assets/javascripts/pager.js.es6 index 25033ea659f..2497c9e22b5 100644 --- a/app/assets/javascripts/pager.js.es6 +++ b/app/assets/javascripts/pager.js.es6 @@ -1,9 +1,9 @@ (() => { const Pager = { - init(limit, preload, disable, callback) { - this.limit = limit != null ? limit : 0; - this.disable = disable != null ? disable : false; - this.callback = callback != null ? callback : $.noop; + init(limit = 0, preload = false, disable = false, callback = $.noop) { + this.limit = limit; + this.disable = disable; + this.callback = callback; this.loading = $('.loading').first(); if (preload) { this.offset = 0; @@ -13,6 +13,7 @@ } this.initLoadMore(); }, + getOld() { this.loading.show(); $.ajax({ @@ -27,6 +28,7 @@ dataType: 'json', }); }, + append(count, html) { $('.content_list').append(html); if (count > 0) { @@ -35,6 +37,7 @@ this.disable = true; } }, + initLoadMore() { $(document).unbind('scroll'); $(document).endlessScroll({ From 8d39770680499407e6468a345389cd58a1682a80 Mon Sep 17 00:00:00 2001 From: Mike Greiling Date: Sun, 20 Nov 2016 01:02:33 -0600 Subject: [PATCH 6/9] continue to auto-load content while the window is not scrollable --- app/assets/javascripts/pager.js.es6 | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/app/assets/javascripts/pager.js.es6 b/app/assets/javascripts/pager.js.es6 index 2497c9e22b5..c4cfd011e0f 100644 --- a/app/assets/javascripts/pager.js.es6 +++ b/app/assets/javascripts/pager.js.es6 @@ -20,10 +20,17 @@ type: 'GET', url: $('.content_list').data('href') || window.location.href, data: `limit=${this.limit}&offset=${this.offset}`, - complete: () => this.loading.hide(), + error: () => this.loading.hide(), success: (data) => { - Pager.append(data.count, data.html); - Pager.callback(); + this.append(data.count, data.html); + this.callback(); + + // keep loading until we've filled the viewport height + if (!this.isScrollable()) { + this.getOld(); + } else { + this.loading.hide(); + } }, dataType: 'json', }); @@ -38,17 +45,21 @@ } }, + isScrollable() { + return $(document).height() > $(window).height() + $(window).scrollTop() + 400; + }, + initLoadMore() { $(document).unbind('scroll'); $(document).endlessScroll({ bottomPixels: 400, fireDelay: 1000, fireOnce: true, - ceaseFire: () => Pager.disable !== true, + ceaseFire: () => this.disable === true, callback: () => { if (!this.loading.is(':visible')) { this.loading.show(); - Pager.getOld(); + this.getOld(); } }, }); From 1166b380cd2fba7bd5ee99f3fe7d0c5b1a677e73 Mon Sep 17 00:00:00 2001 From: Mike Greiling Date: Sun, 20 Nov 2016 01:11:47 -0600 Subject: [PATCH 7/9] prevent infinite loop when no content is returned --- app/assets/javascripts/pager.js.es6 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/javascripts/pager.js.es6 b/app/assets/javascripts/pager.js.es6 index c4cfd011e0f..f0ae8950c5f 100644 --- a/app/assets/javascripts/pager.js.es6 +++ b/app/assets/javascripts/pager.js.es6 @@ -26,7 +26,7 @@ this.callback(); // keep loading until we've filled the viewport height - if (!this.isScrollable()) { + if (data.count > 0 && !this.isScrollable()) { this.getOld(); } else { this.loading.hide(); From ddab50b9082a74810631e138d7931a0ebf116751 Mon Sep 17 00:00:00 2001 From: Mike Greiling Date: Sun, 20 Nov 2016 01:22:59 -0600 Subject: [PATCH 8/9] add CHANGELOG entry for !7608 --- .../24499-fix-activity-autoload-on-large-viewports.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 changelogs/unreleased/24499-fix-activity-autoload-on-large-viewports.yml diff --git a/changelogs/unreleased/24499-fix-activity-autoload-on-large-viewports.yml b/changelogs/unreleased/24499-fix-activity-autoload-on-large-viewports.yml new file mode 100644 index 00000000000..53dcc2a82f1 --- /dev/null +++ b/changelogs/unreleased/24499-fix-activity-autoload-on-large-viewports.yml @@ -0,0 +1,4 @@ +--- +title: Fix activity page endless scroll on large viewports +merge_request: 7608 +author: From 0dd95ca98381b4c6fc7016dd50dd3052051491b0 Mon Sep 17 00:00:00 2001 From: Mike Greiling Date: Mon, 21 Nov 2016 10:17:11 -0600 Subject: [PATCH 9/9] fix some code style issues according to feedback --- app/assets/javascripts/activities.js.es6 | 11 ++++++----- app/assets/javascripts/pager.js.es6 | 17 ++++++++++------- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/app/assets/javascripts/activities.js.es6 b/app/assets/javascripts/activities.js.es6 index da8a4a8f3a2..19bcfef89fb 100644 --- a/app/assets/javascripts/activities.js.es6 +++ b/app/assets/javascripts/activities.js.es6 @@ -5,9 +5,9 @@ class Activities { constructor() { Pager.init(20, true, false, this.updateTooltips); - $('.event-filter-link').on('click', (event) => { - event.preventDefault(); - this.toggleFilter($(event.currentTarget)); + $('.event-filter-link').on('click', (e) => { + e.preventDefault(); + this.toggleFilter(e.currentTarget); this.reloadActivities(); }); } @@ -22,12 +22,13 @@ } toggleFilter(sender) { - const filter = sender.attr('id').split('_')[0]; + const $sender = $(sender); + const filter = $sender.attr('id').split('_')[0]; $('.event-filter .active').removeClass('active'); Cookies.set('event_filter', filter); - sender.closest('li').toggleClass('active'); + $sender.closest('li').toggleClass('active'); } } diff --git a/app/assets/javascripts/pager.js.es6 b/app/assets/javascripts/pager.js.es6 index f0ae8950c5f..e35cf6d295e 100644 --- a/app/assets/javascripts/pager.js.es6 +++ b/app/assets/javascripts/pager.js.es6 @@ -1,15 +1,17 @@ (() => { + const ENDLESS_SCROLL_BOTTOM_PX = 400; + const ENDLESS_SCROLL_FIRE_DELAY_MS = 1000; + const Pager = { init(limit = 0, preload = false, disable = false, callback = $.noop) { this.limit = limit; + this.offset = this.limit; this.disable = disable; this.callback = callback; this.loading = $('.loading').first(); if (preload) { this.offset = 0; this.getOld(); - } else { - this.offset = this.limit; } this.initLoadMore(); }, @@ -20,19 +22,19 @@ type: 'GET', url: $('.content_list').data('href') || window.location.href, data: `limit=${this.limit}&offset=${this.offset}`, + dataType: 'json', error: () => this.loading.hide(), success: (data) => { this.append(data.count, data.html); this.callback(); // keep loading until we've filled the viewport height - if (data.count > 0 && !this.isScrollable()) { + if (!this.disable && !this.isScrollable()) { this.getOld(); } else { this.loading.hide(); } }, - dataType: 'json', }); }, @@ -46,14 +48,15 @@ }, isScrollable() { - return $(document).height() > $(window).height() + $(window).scrollTop() + 400; + const $w = $(window); + return $(document).height() > $w.height() + $w.scrollTop() + ENDLESS_SCROLL_BOTTOM_PX; }, initLoadMore() { $(document).unbind('scroll'); $(document).endlessScroll({ - bottomPixels: 400, - fireDelay: 1000, + bottomPixels: ENDLESS_SCROLL_BOTTOM_PX, + fireDelay: ENDLESS_SCROLL_FIRE_DELAY_MS, fireOnce: true, ceaseFire: () => this.disable === true, callback: () => {