branch develop updated (35884647 -> 98e57e63)
This is an automated email from the git hooks/post-receive script. New change to branch develop in repository pollen. See https://gitlab.nuiton.org/chorem/pollen.git from 35884647 refs #136 oubli des videos new 98e57e63 chargement en lazy des votes (ref #131) The 1 revisions listed above as "new" are entirely new to this repository and will be described in separate emails. The revisions listed as "adds" were already present in the repository and have only been added to this reference. Detailed log of new commits: commit 98e57e63dc89f630e6143ecc06e344ea1329d726 Author: Sylvain Bavencoff <bavencoff@codelutin.com> Date: Wed Sep 13 10:52:59 2017 +0200 chargement en lazy des votes (ref #131) Summary of changes: .../org/chorem/pollen/rest/api/v1/VoteApi.java | 11 +- pollen-services/src/main/config/PollenServices.ini | 6 + .../pollen/services/service/VoteService.java | 27 ++++- .../i18n/pollen-services_en_GB.properties | 1 + .../i18n/pollen-services_fr_FR.properties | 1 + pollen-ui-riot-js/src/main/web/js/Poll.js | 31 ++--- pollen-ui-riot-js/src/main/web/js/VoteService.js | 8 +- .../src/main/web/tag/components/LazyLoad.tag.html | 33 +++--- .../src/main/web/tag/poll/Votes.tag.html | 128 +++++++++++++++------ 9 files changed, 173 insertions(+), 73 deletions(-) -- To stop receiving notification emails like this one, please contact chorem.org SCM administrator <admin+scm@chorem.org>.
This is an automated email from the git hooks/post-receive script. New commit to branch develop in repository pollen. See https://gitlab.nuiton.org/chorem/pollen.git commit 98e57e63dc89f630e6143ecc06e344ea1329d726 Author: Sylvain Bavencoff <bavencoff@codelutin.com> Date: Wed Sep 13 10:52:59 2017 +0200 chargement en lazy des votes (ref #131) --- .../org/chorem/pollen/rest/api/v1/VoteApi.java | 11 +- pollen-services/src/main/config/PollenServices.ini | 6 + .../pollen/services/service/VoteService.java | 27 ++++- .../i18n/pollen-services_en_GB.properties | 1 + .../i18n/pollen-services_fr_FR.properties | 1 + pollen-ui-riot-js/src/main/web/js/Poll.js | 31 ++--- pollen-ui-riot-js/src/main/web/js/VoteService.js | 8 +- .../src/main/web/tag/components/LazyLoad.tag.html | 33 +++--- .../src/main/web/tag/poll/Votes.tag.html | 128 +++++++++++++++------ 9 files changed, 173 insertions(+), 73 deletions(-) diff --git a/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/VoteApi.java b/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/VoteApi.java index 1661a71c..80ac2ae5 100644 --- a/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/VoteApi.java +++ b/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/VoteApi.java @@ -23,12 +23,15 @@ package org.chorem.pollen.rest.api.v1; import org.chorem.pollen.persistence.entity.Poll; import org.chorem.pollen.persistence.entity.Vote; +import org.chorem.pollen.services.bean.PaginationParameterBean; +import org.chorem.pollen.services.bean.PaginationResultBean; import org.chorem.pollen.services.bean.PollenEntityId; import org.chorem.pollen.services.bean.PollenEntityRef; import org.chorem.pollen.services.bean.VoteBean; import org.chorem.pollen.services.service.InvalidFormException; import org.chorem.pollen.services.service.VoteService; +import javax.ws.rs.BeanParam; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; import javax.ws.rs.GET; @@ -39,7 +42,6 @@ import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; -import java.util.List; /** * TODO @@ -63,10 +65,11 @@ public class VoteApi { @Path("/polls/{pollId}/votes") @GET - public List<VoteBean> getVotes(@Context VoteService voteService, - @PathParam("pollId") PollenEntityId<Poll> pollId) { + public PaginationResultBean<VoteBean> getVotes(@Context VoteService voteService, + @PathParam("pollId") PollenEntityId<Poll> pollId, + @BeanParam PaginationParameterBean paginationParameter) { - return voteService.getVotes(pollId.getEntityId()); + return voteService.getVotes(pollId.getEntityId(), paginationParameter); } diff --git a/pollen-services/src/main/config/PollenServices.ini b/pollen-services/src/main/config/PollenServices.ini index 852fd00e..f6a42182 100644 --- a/pollen-services/src/main/config/PollenServices.ini +++ b/pollen-services/src/main/config/PollenServices.ini @@ -101,6 +101,12 @@ key = pollen.default.commentPageSize type = int defaultValue = 10 +[option defaultVotePageSize] +description = pollen.configuration.defaultVotePageSize +key = pollen.default.votePageSize +type = int +defaultValue = 10 + [option defaultFavoriteListPageSize] description = pollen.configuration.defaultFavoriteListPageSize key = pollen.default.favoriteListPageSize diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/service/VoteService.java b/pollen-services/src/main/java/org/chorem/pollen/services/service/VoteService.java index 4b1f2574..c2e2838e 100644 --- a/pollen-services/src/main/java/org/chorem/pollen/services/service/VoteService.java +++ b/pollen-services/src/main/java/org/chorem/pollen/services/service/VoteService.java @@ -33,12 +33,16 @@ import org.chorem.pollen.persistence.entity.VoteToChoiceTopiaDao; import org.chorem.pollen.persistence.entity.VoterList; import org.chorem.pollen.persistence.entity.VoterListMember; import org.chorem.pollen.services.bean.ChoiceBean; +import org.chorem.pollen.services.bean.PaginationParameterBean; +import org.chorem.pollen.services.bean.PaginationResultBean; import org.chorem.pollen.services.bean.PollenEntityRef; import org.chorem.pollen.services.bean.ReportResumeBean; import org.chorem.pollen.services.bean.VoteBean; import org.chorem.pollen.services.bean.VoteToChoiceBean; import org.chorem.pollen.services.service.security.PermissionVerb; import org.chorem.pollen.votecounting.VoteCounting; +import org.nuiton.util.pagination.PaginationParameter; +import org.nuiton.util.pagination.PaginationResult; import java.util.ArrayList; import java.util.Collection; @@ -103,7 +107,7 @@ public class VoteService extends PollenServiceSupport { } - public List<VoteBean> getVotes(String pollId) { + public PaginationResultBean<VoteBean> getVotes(String pollId, PaginationParameterBean paginationParameter) { checkNotNull(pollId); @@ -117,7 +121,9 @@ public class VoteService extends PollenServiceSupport { } } - return toBeanList(VoteBean.class, votes, voteBeanFunction); + PaginationResult<Vote> votePaginationResult = PaginationResult.fromFullList(votes, getPaginationParameter(paginationParameter)); + + return toPaginationListBean(VoteBean.class, votePaginationResult, voteBeanFunction); } @@ -424,4 +430,21 @@ public class VoteService extends PollenServiceSupport { return getVoteDao().forPollEquals(poll).count(); } + + protected PaginationParameter getPaginationParameter(PaginationParameterBean paginationParameter) { + + if (paginationParameter == null) { + + int pageSize = getPollenServiceConfig().getDefaultVotePageSize(); + paginationParameter = PaginationParameterBean.of( + 0, + pageSize, + Vote.PROPERTY_TOPIA_CREATE_DATE, + true); + + } + + return paginationParameter.toPaginationParameter(); + + } } diff --git a/pollen-services/src/main/resources/i18n/pollen-services_en_GB.properties b/pollen-services/src/main/resources/i18n/pollen-services_en_GB.properties index 69f6e9af..b41d405e 100644 --- a/pollen-services/src/main/resources/i18n/pollen-services_en_GB.properties +++ b/pollen-services/src/main/resources/i18n/pollen-services_en_GB.properties @@ -19,6 +19,7 @@ pollen.configuration.defaultPollenUserPageSize=Default number of users per pages pollen.configuration.defaultResultVisibility=Default Result visibility pollen.configuration.defaultVoteCountingType=Default vote counting type used when creating a new poll pollen.configuration.defaultVoteNotification=Default notification type for the votes of a poll +pollen.configuration.defaultVotePageSize=Default number of vote per page pollen.configuration.defaultVoteVisibility=Default vote visiblity pollen.configuration.devMode=Dev mode pollen.configuration.feedback.locale=locale to send feedback diff --git a/pollen-services/src/main/resources/i18n/pollen-services_fr_FR.properties b/pollen-services/src/main/resources/i18n/pollen-services_fr_FR.properties index 9beac41c..2a17b57e 100644 --- a/pollen-services/src/main/resources/i18n/pollen-services_fr_FR.properties +++ b/pollen-services/src/main/resources/i18n/pollen-services_fr_FR.properties @@ -19,6 +19,7 @@ pollen.configuration.defaultPollenUserPageSize=Nombre d'utilisateurs par page pollen.configuration.defaultResultVisibility=Visibilité des résultats par défaut pollen.configuration.defaultVoteCountingType=Type de dépouillement par défaut lors de la création d'un nouveau sondage pollen.configuration.defaultVoteNotification=Type de notification par défaut pour les votes +pollen.configuration.defaultVotePageSize=Nombre de votes par page pollen.configuration.defaultVoteVisibility=Visibilité des votes par défaut pollen.configuration.devMode=Mode développement pollen.configuration.feedback.locale=La locale pour envoyer les retours utlisateur diff --git a/pollen-ui-riot-js/src/main/web/js/Poll.js b/pollen-ui-riot-js/src/main/web/js/Poll.js index 8815ae0f..6500acbb 100644 --- a/pollen-ui-riot-js/src/main/web/js/Poll.js +++ b/pollen-ui-riot-js/src/main/web/js/Poll.js @@ -16,7 +16,6 @@ class Poll { constructor() { this.choices = []; - this.votes = []; this.comments = []; } @@ -32,7 +31,6 @@ class Poll { this.votePermission = permission; } this.choices = undefined; - this.votes = undefined; this.comments = undefined; this.results = undefined; bus.trigger("poll", this); @@ -64,7 +62,6 @@ class Poll { delete this.permission; delete this._initPromise; this.choices = []; - this.votes = []; this.comments = []; bus.trigger("poll", this); }); @@ -124,12 +121,23 @@ class Poll { return Promise.reject("Init poll after add choice"); } - loadVotes() { + loadLazyVotes(pagination) { + if (this._initPromise) { + return voteService.getVotes(this.id, pagination, this.votePermission || this.permission).then((result) => { + if (this.voteIsVisible) { + this.voteCount = result.pagination.count; + } + return result; + }); + } + return Promise.reject("Init poll after load votes"); + } + + loadForVotes() { if (this._initPromise) { return this._initPromise.then(() => { var promises = [ choiceService.getChoices(this.id, this.permission || this.votePermission), - voteService.getVotes(this.id, this.votePermission || this.permission), voteCountingTypeService.getVoteCountingType(this.voteCountingType) ]; if (this.resultIsVisible) { @@ -143,11 +151,6 @@ class Poll { this.choices = resultsArray[indexResult++]; this.choiceCount = this.choices.length; - this.votes = resultsArray[indexResult++]; - if (this.voteIsVisible) { - this.voteCount = this.votes.length; - } - this.voteCountingTypeValue = resultsArray[indexResult++]; if (this.resultIsVisible) { @@ -295,9 +298,7 @@ class Poll { this.voteId = result.id; this.votePermission = result.permission; - return this.reloadPoll().then(() => { - return this.loadVotes(); - }); + return this.reloadPoll(); }); } return Promise.reject("Init poll after add vote"); @@ -306,7 +307,7 @@ class Poll { updateVote(vote) { if (this.id) { return voteService.updateVote(this.id, vote, this.votePermission || this.permission || vote.permission || "").then(() => { - return Promise.all([this.reloadPoll(), this.loadVotes()]); + return this.reloadPoll(); }); } return Promise.reject("Init poll after update vote"); @@ -315,7 +316,7 @@ class Poll { deleteVote(vote) { if (this.id) { return voteService.deleteVote(this.id, vote.id, this.votePermission || this.permission || vote.permission || "").then(() => { - return Promise.all([this.reloadPoll(), this.loadVotes()]); + return this.reloadPoll(); }); } return Promise.reject("Init poll after delete vote"); diff --git a/pollen-ui-riot-js/src/main/web/js/VoteService.js b/pollen-ui-riot-js/src/main/web/js/VoteService.js index 2805c44b..dee0fdf7 100644 --- a/pollen-ui-riot-js/src/main/web/js/VoteService.js +++ b/pollen-ui-riot-js/src/main/web/js/VoteService.js @@ -31,9 +31,13 @@ class VoteService extends FetchService { return url; } - getVotes(pollId, permission) { + getVotes(pollId, pagination, permission) { + let params = Object.assign({}, pagination); + if (permission) { + params.permission = permission; + } let url = this._getUrlPrefix(pollId); - return this.get(url, {permission: permission}); + return this.get(url, params); } addVote(pollId, form, permission) { diff --git a/pollen-ui-riot-js/src/main/web/tag/components/LazyLoad.tag.html b/pollen-ui-riot-js/src/main/web/tag/components/LazyLoad.tag.html index a0259021..3338d228 100644 --- a/pollen-ui-riot-js/src/main/web/tag/components/LazyLoad.tag.html +++ b/pollen-ui-riot-js/src/main/web/tag/components/LazyLoad.tag.html @@ -2,33 +2,39 @@ <virtual each={element, index in elements}> <yield from="element"/> </virtual> - <div show={nbNext > 0} ref="loading"> + <div show={nbNext > 0} ref="loading" class="loading"> <yield from="loading"/> </div> <script type="es6"> this.reload = () => { - this.elements = []; - this.nbNext = 1; - this.opts.pagination.pageSize = this.opts.loadSize; - this.opts.pagination.pageNumber = -1; - this.loadNext(); + if (!this.loading) { + this.elements = []; + this.nbNext = 1; + this.opts.pagination.pageSize = this.opts.loadSize; + this.opts.pagination.pageNumber = -1; + return this.loadNext(); + } + return Promise.reject(); }; this.loadNext = () => { if (!this.loading && this.nbNext > 0) { this.opts.pagination.pageNumber++; this.loading = true; - this.opts.onload(this.opts.pagination).then(result => { + return this.opts.onload(this.opts.pagination).then(result => { this.elements = this.elements.concat(result.elements); this.opts.pagination = result.pagination; + this.opts.pagination.pageNumber = result.pagination.currentPage; this.nbNext = this.opts.pagination.count - this.elements.length; this.nbNextGroup = Math.min(this.opts.loadSize, this.nbNext); this.loading = false; this.update(); + return Promise.resolve(); }); } + return Promise.reject(); }; this.onscroll = e => { @@ -37,15 +43,14 @@ // " - height window : " + e.currentTarget.clientHeight + // " - top loading : " + this.refs.loading.offsetTop); if (e.currentTarget.scrollTop + e.currentTarget.clientHeight > this.refs.loading.offsetTop) { - this.loadNext(); + this.loadNext().then(() => {}, () => {}); } } else { - // this.logger.info("scroll Y : " + e.currentTarget.scrollY + - // " - height : " + e.currentTarget.innerHeight + - // " - doc.height : " + e.target.body.children[0].clientHeight + - // " - loading.height : " + this.refs.loading.clientHeight); - if (e.currentTarget.scrollY + e.currentTarget.innerHeight > e.target.body.children[0].clientHeight - this.refs.loading.clientHeight) { - this.loadNext(); + let absolutTop = this.refs.loading.getBoundingClientRect().top; + // this.logger.info("absolutTop : " + absolutTop + + // " - height : " + e.currentTarget.innerHeight); + if (0 < absolutTop && absolutTop < e.currentTarget.innerHeight) { + this.loadNext().then(() => {}, () => {}); } } }; diff --git a/pollen-ui-riot-js/src/main/web/tag/poll/Votes.tag.html b/pollen-ui-riot-js/src/main/web/tag/poll/Votes.tag.html index 27d679d7..73e1314e 100644 --- a/pollen-ui-riot-js/src/main/web/tag/poll/Votes.tag.html +++ b/pollen-ui-riot-js/src/main/web/tag/poll/Votes.tag.html @@ -2,6 +2,7 @@ require("./Choice.tag.html"); require("./ChoiceView.tag.html"); require("./Podium.tag.html"); require("../components/HumanInput.tag.html"); +require("../components/LazyLoad.tag.html"); <Votes> <div class="container" show="{loaded}"> @@ -135,7 +136,7 @@ require("../components/HumanInput.tag.html"); </form> <!-- Show votes --> - <div class="voters" if="{poll.resultIsVisible && poll.votes && poll.votes.length > 0}"> + <div class="voters" if="{poll.resultIsVisible}"> <div class="row header separator-bottom"> <div></div> <div class="choices separator-left" if="{showChoiceHeader}"> @@ -145,36 +146,56 @@ require("../components/HumanInput.tag.html"); </div> </div> </div> - <div each="{vote, index in poll.votes}" class="row separator-bottom separator-right"> - <div class="name separator-left"> - <div class="voter-name" onmouseenter="{parent.showTooltip(vote)}" onclick="{parent.showTooltip(vote)}" onmouseleave="{parent.hideTooltip}"> - <i class="fa fa-user-circle c-icon"></i> - <span if="{!vote.anonymous}">{vote.voterName}</span> - <span if="{vote.anonymous}" class="anonymous-voter">{parent.__.anonymousVoter}</span> + <LazyLoad pagination={pagination} onload={lazyLoad} load-size="20" not-load-on-start="true" ref="lazyLoad" class="elements"> + <yield to="element"> + <div class="row separator-bottom separator-right"> + <div class="name separator-left"> + <div class="voter-name" onmouseenter="{parent.parent.showTooltip(element)}" onclick="{parent.parent.showTooltip(vote)}" onmouseleave="{parent.parent.hideTooltip}"> + <i class="fa fa-user-circle c-icon"></i> + <span if="{!element.anonymous}">{element.voterName}</span> + <span if="{element.anonymous}" class="anonymous-voter">{parent.__.anonymousVoter}</span> + </div> + <button type="button" + class="c-button c-button--rounded u-xsmall c-button--brand" + if="{!parent.parent.poll.closed && element.permission}" + disabled="{parent.parent.voteInEdition != null || parent.parent.voting}" + onclick="{parent.parent.onEditVote(element)}"> + <i class="fa fa-pencil-square-o"></i> + </button> + <button type="button" + class="c-button c-button--rounded u-xsmall c-button--error" + if="{!parent.parent.poll.closed && (parent.parent.poll.permission || element.permission)}" + disabled="{parent.parent.voteInEdition != null || parent.parent.voting}" + onclick="{parent.parent.deleteVote(element)}"> + <i class="fa fa-trash"></i> + </button> + </div> + <div class="results separator-left" ref="results{index}"> + <div each="{choice in parent.parent.poll.choices}" + class="result separator-right {'checkbox' : parent.parent.pollTypeCheckbox} {'selected' : parent.parent.pollTypeCheckbox && parent.parent.poll.getVoteValue(element, choice) == 1}" + onmouseenter="{parent.parent.parent.showTooltip(element, choice)}" onclick="{parent.parent.parent.showTooltip(element, choice)}" onmouseleave="{parent.parent.parent.hideTooltip}"> + <span if="{!pollTypeCheckbox}">{parent.parent.parent.poll.getVoteValue(element, choice)}</span> + </div> + </div> </div> - <button type="button" - class="c-button c-button--rounded u-xsmall c-button--brand" - if="{!poll.closed && vote.permission}" - disabled="{voteInEdition != null || voting}" - onclick="{parent.onEditVote(vote)}"> - <i class="fa fa-pencil-square-o"></i> - </button> - <button type="button" - class="c-button c-button--rounded u-xsmall c-button--error" - if="{!poll.closed && (poll.permission || vote.permission)}" - disabled="{voteInEdition != null || voting}" - onclick="{parent.deleteVote(vote)}"> - <i class="fa fa-trash"></i> - </button> - </div> - <div class="results separator-left" ref="results{index}"> - <div each="{choice in poll.choices}" - class="result separator-right {'checkbox' : pollTypeCheckbox} {'selected' : pollTypeCheckbox && poll.getVoteValue(vote, choice) == 1}" - onmouseenter="{parent.showTooltip(vote, choice)}" onclick="{parent.showTooltip(vote, choice)}" onmouseleave="{parent.hideTooltip}"> - <span if="{!pollTypeCheckbox}">{poll.getVoteValue(vote, choice)}</span> + </yield> + <yield to="loading"> + <div class="row separator-bottom separator-right"> + <div class="name separator-left"> + <div class="voter-name"> + <i class="fa fa-user-circle c-icon"></i> + <i class="fa fa-spinner fa-pulse"></i> + </div> + </div> + <div class="results separator-left" ref="results{index}"> + <div each="{choice in parent.poll.choices}" + class="result separator-right"> + <i class="fa fa-spinner fa-pulse"></i> + </div> + </div> </div> - </div> - </div> + </yield> + </LazyLoad> <div class="vote-tooltip" ref="voteTooltip" show="{voteTooltip.show}"> <ChoiceView if="{voteTooltip.choice}" choice="{voteTooltip.choice}" center="true" hideReport="true"></ChoiceView> @@ -202,15 +223,33 @@ require("../components/HumanInput.tag.html"); this.addingChoice = false; this.poll = require("../../js/Poll.js"); - this.poll.loadVotes().then(() => { - this.updateShowChoiceContainer(); + this.poll.loadForVotes().then(() => { + this.refresh(); this.update(); }); + + this.pagination = { + order: "topiaCreateDate", + desc: true + }; + + this.lazyLoad = pagination => { + return this.poll.loadLazyVotes(pagination).then((result) => { + return result; + }); + }; + + this.refresh = () => { + this.refs.lazyLoad && this.refs.lazyLoad.reload().then(() => { + this.updateShowChoiceContainer(); + }, () => {}); + }; + this.choiceToAdd = this.poll.initChoice(); this.updateShowChoiceContainer = () => { - this.showChoiceHeader = this.refs.results0 - && this.refs.results0.offsetWidth / this.poll.choices.length >= MIN_CHOICE_COLUMN_WIDTH; + let results0 = this.refs.lazyLoad.refs.results0; + this.showChoiceHeader = results0 && results0.offsetWidth / this.poll.choices.length >= MIN_CHOICE_COLUMN_WIDTH; }; this.onPollChange = poll => { @@ -219,13 +258,14 @@ require("../components/HumanInput.tag.html"); this.pollTypeCheckbox = poll.voteCountingTypeValue && poll.voteCountingTypeValue.renderType === "checkbox"; this.choiceToAdd = this.poll.initChoice(this.choiceToAdd); this.onVoteChanged(); + this.refresh(); this.update(); }; this.listen("poll", this.onPollChange); this.listen("user", (user, oldUser) => { - if (user != oldUser) { - this.poll.loadVotes(); + if (user !== oldUser) { + this.refresh(); this.update(); } }); @@ -319,6 +359,9 @@ require("../components/HumanInput.tag.html"); this.poll.addVote(vote).then(() => { this.resetPoll(); + if (this.poll.voteIsVisible) { + this.refresh(); + } if (this.poll.resultIsVisible) { this.poll.loadResults().then(() => { this.voting = false; @@ -364,6 +407,9 @@ require("../components/HumanInput.tag.html"); this.poll.updateVote(updateVote).then(() => { this.voteInEdition = null; this.resetPoll(); + if (this.poll.voteIsVisible) { + this.refresh(); + } if (this.poll.resultIsVisible) { this.poll.loadResults().then(() => { this.voting = false; @@ -585,6 +631,15 @@ require("../components/HumanInput.tag.html"); margin-top: 50px; } + .voters .elements, + .voters .loading { + width: 100%; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + } + .voters .row { display: flex; width: 95%; @@ -629,7 +684,8 @@ require("../components/HumanInput.tag.html"); overflow: visible; } - .voters .results, .voters .choices { + .voters .results, + .voters .choices { display: flex; width: 100%; } -- To stop receiving notification emails like this one, please contact chorem.org SCM administrator <admin+scm@chorem.org>.
participants (1)
-
chorem.org scm