summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md17
-rw-r--r--Stackerfile.yml2
-rw-r--r--client/components/lists/list.styl3
-rw-r--r--client/components/lists/listBody.jade12
-rw-r--r--client/components/lists/listBody.js83
-rw-r--r--package.json2
-rw-r--r--sandstorm-pkgdef.capnp4
7 files changed, 117 insertions, 6 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index de9ec68f..1d101b66 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,20 @@
+# v2.13 2019-02-01 Wekan release
+
+This release adds the following new features with Apache I-CLA, thanks to bentiss:
+
+- [Use infinite-scrolling on lists](https://github.com/wekan/wekan/pull/2144).
+ This allows to reduce the loading time of a big board.
+ Note that there is an infinite scroll implementation in the mixins,
+ but this doesn't fit well as the cards in the list can have arbitrary
+ height.
+ The idea to rely on the visibility of a spinner is based on
+ http://www.meteorpedia.com/read/Infinite_Scrolling
+- [When writing to minicard, press Shift-Enter on minicard to go to next line
+ below](https://github.com/wekan/wekan/commit/7a35099fb9778d5f3656a57c74af426cfb20fba3),
+ to continue writing on same minicard 2nd line.
+
+Thanks to GitHub user bentiss for contributions.
+
# v2.12 2019-01-31 Wekan release
This release fixes the following bugs:
diff --git a/Stackerfile.yml b/Stackerfile.yml
index f0f61101..523ba2b4 100644
--- a/Stackerfile.yml
+++ b/Stackerfile.yml
@@ -1,5 +1,5 @@
appId: wekan-public/apps/77b94f60-dec9-0136-304e-16ff53095928
-appVersion: "v2.12.0"
+appVersion: "v2.13.0"
files:
userUploads:
- README.md
diff --git a/client/components/lists/list.styl b/client/components/lists/list.styl
index 51ade73c..70502083 100644
--- a/client/components/lists/list.styl
+++ b/client/components/lists/list.styl
@@ -211,6 +211,9 @@
max-height: 250px
overflow: hidden
+.sk-spinner-list
+ margin-top: unset !important
+
list-header-color(background, color...)
border-bottom: 6px solid background
diff --git a/client/components/lists/listBody.jade b/client/components/lists/listBody.jade
index c6c9b204..f030833b 100644
--- a/client/components/lists/listBody.jade
+++ b/client/components/lists/listBody.jade
@@ -4,7 +4,7 @@ template(name="listBody")
if cards.count
+inlinedForm(autoclose=false position="top")
+addCardForm(listId=_id position="top")
- each (cards (idOrNull ../../_id))
+ each (cardsWithLimit (idOrNull ../../_id))
a.minicard-wrapper.js-minicard(href=absoluteUrl
class="{{#if cardIsSelected}}is-selected{{/if}}"
class="{{#if MultiSelection.isSelected _id}}is-checked{{/if}}")
@@ -12,6 +12,16 @@ template(name="listBody")
.materialCheckBox.multi-selection-checkbox.js-toggle-multi-selection(
class="{{#if MultiSelection.isSelected _id}}is-checked{{/if}}")
+minicard(this)
+ if (showSpinner (idOrNull ../../_id))
+ .sk-spinner.sk-spinner-wave.sk-spinner-list(
+ class=currentBoard.colorClass
+ id="showMoreResults")
+ .sk-rect1
+ .sk-rect2
+ .sk-rect3
+ .sk-rect4
+ .sk-rect5
+
if canSeeAddCard
+inlinedForm(autoclose=false position="bottom")
+addCardForm(listId=_id position="bottom")
diff --git a/client/components/lists/listBody.js b/client/components/lists/listBody.js
index 1001f3bc..0f5caac5 100644
--- a/client/components/lists/listBody.js
+++ b/client/components/lists/listBody.js
@@ -1,6 +1,34 @@
const subManager = new SubsManager();
+const InfiniteScrollIter = 10;
BlazeComponent.extendComponent({
+ onCreated() {
+ // for infinite scrolling
+ this.cardlimit = new ReactiveVar(InfiniteScrollIter);
+ },
+
+ onRendered() {
+ const domElement = this.find('.js-perfect-scrollbar');
+
+ this.$(domElement).on('scroll', () => this.updateList(domElement));
+ $(window).on(`resize.${this.data().listId}`, () => this.updateList(domElement));
+
+ // we add a Mutation Observer to allow propagations of cardlimit
+ // when the spinner stays in the current view (infinite scrolling)
+ this.mutationObserver = new MutationObserver(() => this.updateList(domElement));
+
+ this.mutationObserver.observe(domElement, {
+ childList: true,
+ });
+
+ this.updateList(domElement);
+ },
+
+ onDestroyed() {
+ $(window).off(`resize.${this.data().listId}`);
+ this.mutationObserver.disconnect();
+ },
+
mixins() {
return [Mixins.PerfectScrollbar];
},
@@ -60,6 +88,13 @@ BlazeComponent.extendComponent({
type: 'cardType-card',
});
+ // if the displayed card count is less than the total cards in the list,
+ // we need to increment the displayed card count to prevent the spinner
+ // to appear
+ const cardCount = this.data().cards(this.idOrNull(swimlaneId)).count();
+ if (this.cardlimit.get() < cardCount) {
+ this.cardlimit.set(this.cardlimit.get() + InfiniteScrollIter);
+ }
// In case the filter is active we need to add the newly inserted card in
// the list of exceptions -- cards that are not filtered. Otherwise the
@@ -119,6 +154,52 @@ BlazeComponent.extendComponent({
return undefined;
},
+ cardsWithLimit(swimlaneId) {
+ const limit = this.cardlimit.get();
+ const selector = {
+ listId: this.currentData()._id,
+ archived: false,
+ };
+ if (swimlaneId)
+ selector.swimlaneId = swimlaneId;
+ return Cards.find(Filter.mongoSelector(selector), {
+ sort: ['sort'],
+ limit,
+ });
+ },
+
+ spinnerInView(container) {
+ const parentViewHeight = container.clientHeight;
+ const bottomViewPosition = container.scrollTop + parentViewHeight;
+
+ const spinner = this.find('.sk-spinner-list');
+
+ const threshold = spinner.offsetTop;
+
+ return bottomViewPosition > threshold;
+ },
+
+ showSpinner(swimlaneId) {
+ const list = Template.currentData();
+ return list.cards(swimlaneId).count() > this.cardlimit.get();
+ },
+
+ updateList(container) {
+ // first, if the spinner is not rendered, we have reached the end of
+ // the list of cards, so skip and disable firing the events
+ const target = this.find('.sk-spinner-list');
+ if (!target) {
+ this.$(container).off('scroll');
+ $(window).off(`resize.${this.data().listId}`);
+ return;
+ }
+
+ if (this.spinnerInView(container)) {
+ this.cardlimit.set(this.cardlimit.get() + InfiniteScrollIter);
+ Ps.update(container);
+ }
+ },
+
canSeeAddCard() {
return !this.reachedWipLimit() && Meteor.user() && Meteor.user().isBoardMember() && !Meteor.user().isCommentOnly();
},
@@ -179,7 +260,7 @@ BlazeComponent.extendComponent({
pressKey(evt) {
// Pressing Enter should submit the card
- if (evt.keyCode === 13) {
+ if (evt.keyCode === 13 && !evt.shiftKey) {
evt.preventDefault();
const $form = $(evt.currentTarget).closest('form');
// XXX For some reason $form.submit() does not work (it's probably a bug
diff --git a/package.json b/package.json
index 5209c96b..94dd303f 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "wekan",
- "version": "v2.12.0",
+ "version": "v2.13.0",
"description": "Open-Source kanban",
"private": true,
"scripts": {
diff --git a/sandstorm-pkgdef.capnp b/sandstorm-pkgdef.capnp
index d8d80938..19e81a74 100644
--- a/sandstorm-pkgdef.capnp
+++ b/sandstorm-pkgdef.capnp
@@ -22,10 +22,10 @@ const pkgdef :Spk.PackageDefinition = (
appTitle = (defaultText = "Wekan"),
# The name of the app as it is displayed to the user.
- appVersion = 214,
+ appVersion = 215,
# Increment this for every release.
- appMarketingVersion = (defaultText = "2.12.0~2019-01-31"),
+ appMarketingVersion = (defaultText = "2.13.0~2019-02-01"),
# Human-readable presentation of the app version.
minUpgradableAppVersion = 0,