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 fae8b56690bcac9f128343152e408822fb53bcf5 Author: Sylvain Bavencoff <bavencoff@codelutin.com> Date: Wed May 23 15:15:07 2018 +0200 refs #172 : Envoie des mails d'invitations différé --- .../pollen/persistence/entity/PollTopiaDao.java | 7 +- .../entity/VoterListMemberTopiaDao.java | 20 ++++++ .../migration/h2/V3_2_0_1__add_invivation_sent.sql | 3 + .../postgresql/V3_2_0_1__add_invivation_sent.sql | 3 + pollen-persistence/src/main/xmi/pollen.properties | 2 +- pollen-persistence/src/main/xmi/pollen.zargo | Bin 30672 -> 30846 bytes .../chorem/pollen/rest/api/v1/VoterListApi.java | 21 +++++- .../org/chorem/pollen/services/bean/PollBean.java | 10 +++ .../pollen/services/bean/VoterListMemberBean.java | 10 +++ .../services/service/NotificationService.java | 20 +----- .../pollen/services/service/PollService.java | 2 + .../pollen/services/service/VoterListService.java | 71 +++++++++++++------ pollen-ui-riot-js/src/main/web/i18n/en.json | 9 ++- pollen-ui-riot-js/src/main/web/i18n/fr.json | 9 ++- pollen-ui-riot-js/src/main/web/js/PollForm.js | 20 +++++- .../src/main/web/js/VoterListService.js | 20 +++++- .../src/main/web/tag/poll/Summary.tag.html | 76 ++++++++++++++++++--- 17 files changed, 244 insertions(+), 59 deletions(-) diff --git a/pollen-persistence/src/main/java/org/chorem/pollen/persistence/entity/PollTopiaDao.java b/pollen-persistence/src/main/java/org/chorem/pollen/persistence/entity/PollTopiaDao.java index 900d140d..38cd4aee 100644 --- a/pollen-persistence/src/main/java/org/chorem/pollen/persistence/entity/PollTopiaDao.java +++ b/pollen-persistence/src/main/java/org/chorem/pollen/persistence/entity/PollTopiaDao.java @@ -180,8 +180,11 @@ public class PollTopiaDao extends AbstractPollTopiaDao<Poll> { VoterListTopiaDao dao = topiaDaoSupplier .getDao(VoterList.class, VoterListTopiaDao.class); - List<VoterList> list = dao.forPollEquals(entity).findAll(); - dao.deleteAll(list); + dao.forPollEquals(entity) + .addNull(VoterList.PROPERTY_PARENT) + .tryFindUnique() + .toJavaUtil() + .ifPresent(dao::delete); } diff --git a/pollen-persistence/src/main/java/org/chorem/pollen/persistence/entity/VoterListMemberTopiaDao.java b/pollen-persistence/src/main/java/org/chorem/pollen/persistence/entity/VoterListMemberTopiaDao.java index 0c638412..004f3f48 100644 --- a/pollen-persistence/src/main/java/org/chorem/pollen/persistence/entity/VoterListMemberTopiaDao.java +++ b/pollen-persistence/src/main/java/org/chorem/pollen/persistence/entity/VoterListMemberTopiaDao.java @@ -22,6 +22,10 @@ package org.chorem.pollen.persistence.entity; */ +import com.google.common.collect.Maps; + +import java.util.Map; + public class VoterListMemberTopiaDao extends AbstractVoterListMemberTopiaDao<VoterListMember> { @Override @@ -42,4 +46,20 @@ public class VoterListMemberTopiaDao extends AbstractVoterListMemberTopiaDao<Vot } + public long countDistinctMembers(Poll poll, boolean invitationSent) { + String alias = "m"; + String hql = "select count(" + alias + "." + VoterListMember.PROPERTY_MEMBER + "." + PollenPrincipal.PROPERTY_EMAIL + ")" + + " from " + VoterListMember.class.getCanonicalName() + " " + alias + + " where " + alias + "." + VoterListMember.PROPERTY_VOTER_LIST + "." + VoterList.PROPERTY_POLL + " = :" + VoterList.PROPERTY_POLL; + Map<String, Object> params = Maps.newHashMap(); + params.put(VoterList.PROPERTY_POLL, poll); + + if (invitationSent) { + hql += " and " + alias + "." + VoterListMember.PROPERTY_INVITATION_SENT + " = :" + VoterListMember.PROPERTY_INVITATION_SENT; + params.put(VoterListMember.PROPERTY_INVITATION_SENT, true); + } + + return count(hql, params); + } + } diff --git a/pollen-persistence/src/main/resources/db/migration/h2/V3_2_0_1__add_invivation_sent.sql b/pollen-persistence/src/main/resources/db/migration/h2/V3_2_0_1__add_invivation_sent.sql new file mode 100644 index 00000000..c020f704 --- /dev/null +++ b/pollen-persistence/src/main/resources/db/migration/h2/V3_2_0_1__add_invivation_sent.sql @@ -0,0 +1,3 @@ +-- add invitation sent in VoterListMember +alter table voterlistmember add invitationsent boolean; +update voterlistmember set invitationsent = true; \ No newline at end of file diff --git a/pollen-persistence/src/main/resources/db/migration/postgresql/V3_2_0_1__add_invivation_sent.sql b/pollen-persistence/src/main/resources/db/migration/postgresql/V3_2_0_1__add_invivation_sent.sql new file mode 100644 index 00000000..c020f704 --- /dev/null +++ b/pollen-persistence/src/main/resources/db/migration/postgresql/V3_2_0_1__add_invivation_sent.sql @@ -0,0 +1,3 @@ +-- add invitation sent in VoterListMember +alter table voterlistmember add invitationsent boolean; +update voterlistmember set invitationsent = true; \ No newline at end of file diff --git a/pollen-persistence/src/main/xmi/pollen.properties b/pollen-persistence/src/main/xmi/pollen.properties index b8f11682..4c4c9289 100644 --- a/pollen-persistence/src/main/xmi/pollen.properties +++ b/pollen-persistence/src/main/xmi/pollen.properties @@ -18,7 +18,7 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. # #L% ###m -model.tagvalue.version=3.1.0.9 +model.tagvalue.version=3.2.0.1 #model.tagValue.notGenerateToString=true #model.tagValue.constantPrefix=PROPERTY_ #model.tagValue.useEnumerationName=true diff --git a/pollen-persistence/src/main/xmi/pollen.zargo b/pollen-persistence/src/main/xmi/pollen.zargo index 3031d4e4..18196270 100644 Binary files a/pollen-persistence/src/main/xmi/pollen.zargo and b/pollen-persistence/src/main/xmi/pollen.zargo differ diff --git a/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/VoterListApi.java b/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/VoterListApi.java index 082ca982..2b132b12 100644 --- a/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/VoterListApi.java +++ b/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/VoterListApi.java @@ -192,12 +192,29 @@ public class VoterListApi { } + @Path("/polls/{pollId}/voterLists/{voterListId}/send") + @GET + public int sendInvitationVoterList(@Context VoterListService voterListService, + @PathParam("pollId") PollenEntityId<Poll> pollId, + @PathParam("voterListId") PollenEntityId<VoterList> voterListId) { + return voterListService.sendInvitationVoterList(pollId.getEntityId(), voterListId.getEntityId(), false); + } + + @Path("/polls/{pollId}/voterLists/{voterListId}/members/{memberId}/send") + @GET + public boolean sendInvitationMember(@Context VoterListService voterListService, + @PathParam("pollId") PollenEntityId<Poll> pollId, + @PathParam("voterListId") PollenEntityId<VoterList> voterListId, + @PathParam("memberId") PollenEntityId<VoterListMember> memberId) { + return voterListService.sendInvitationMember(pollId.getEntityId(), voterListId.getEntityId(), memberId.getEntityId(), false); + } + @Path("/polls/{pollId}/voterLists/{voterListId}/resend") @GET public int resendInvitationVoterList(@Context VoterListService voterListService, @PathParam("pollId") PollenEntityId<Poll> pollId, @PathParam("voterListId") PollenEntityId<VoterList> voterListId) { - return voterListService.resendInvitationVoterList(pollId.getEntityId(), voterListId.getEntityId()); + return voterListService.sendInvitationVoterList(pollId.getEntityId(), voterListId.getEntityId(), true); } @Path("/polls/{pollId}/voterLists/{voterListId}/members/{memberId}/resend") @@ -206,7 +223,7 @@ public class VoterListApi { @PathParam("pollId") PollenEntityId<Poll> pollId, @PathParam("voterListId") PollenEntityId<VoterList> voterListId, @PathParam("memberId") PollenEntityId<VoterListMember> memberId) { - return voterListService.resendInvitationMember(pollId.getEntityId(), voterListId.getEntityId(), memberId.getEntityId()); + return voterListService.sendInvitationMember(pollId.getEntityId(), voterListId.getEntityId(), memberId.getEntityId(), true); } } diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/bean/PollBean.java b/pollen-services/src/main/java/org/chorem/pollen/services/bean/PollBean.java index 4fda8c9d..e117cac2 100644 --- a/pollen-services/src/main/java/org/chorem/pollen/services/bean/PollBean.java +++ b/pollen-services/src/main/java/org/chorem/pollen/services/bean/PollBean.java @@ -117,6 +117,8 @@ public class PollBean extends PollenBean<Poll> { protected long participantCount; + protected long participantInvitedCount; + protected long choiceCount; protected PollStatus status; @@ -436,6 +438,14 @@ public class PollBean extends PollenBean<Poll> { this.participantCount = participantCount; } + public long getParticipantInvitedCount() { + return participantInvitedCount; + } + + public void setParticipantInvitedCount(long participantInvitedCount) { + this.participantInvitedCount = participantInvitedCount; + } + public ReportResumeBean getReport() { return report; } diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/bean/VoterListMemberBean.java b/pollen-services/src/main/java/org/chorem/pollen/services/bean/VoterListMemberBean.java index c354436d..2a0d21f2 100644 --- a/pollen-services/src/main/java/org/chorem/pollen/services/bean/VoterListMemberBean.java +++ b/pollen-services/src/main/java/org/chorem/pollen/services/bean/VoterListMemberBean.java @@ -40,6 +40,8 @@ public class VoterListMemberBean extends PollenBean<VoterListMember> { protected PollenEntityId<VoterList> voterListId; + protected boolean invitationSent; + protected boolean voting; protected boolean invalidEmail; @@ -83,6 +85,14 @@ public class VoterListMemberBean extends PollenBean<VoterListMember> { this.voterListId = voterListId; } + public boolean isInvitationSent() { + return invitationSent; + } + + public void setInvitationSent(boolean invitationSent) { + this.invitationSent = invitationSent; + } + public boolean isVoting() { return voting; } diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/service/NotificationService.java b/pollen-services/src/main/java/org/chorem/pollen/services/service/NotificationService.java index 34976bf9..8b576a06 100644 --- a/pollen-services/src/main/java/org/chorem/pollen/services/service/NotificationService.java +++ b/pollen-services/src/main/java/org/chorem/pollen/services/service/NotificationService.java @@ -32,7 +32,6 @@ import org.chorem.pollen.persistence.entity.PollenUserEmailAddress; import org.chorem.pollen.persistence.entity.Report; import org.chorem.pollen.persistence.entity.UserCredential; import org.chorem.pollen.persistence.entity.Vote; -import org.chorem.pollen.persistence.entity.VoterList; import org.chorem.pollen.persistence.entity.VoterListMember; import org.chorem.pollen.services.service.mail.ChoiceAddedEmail; import org.chorem.pollen.services.service.mail.ChoiceReportEmail; @@ -202,23 +201,6 @@ public class NotificationService extends PollenServiceSupport { } } - if (PollType.RESTRICTED.equals(poll.getPollType())) { - - VoterList mainVoterList = getVoterListDao() - .forPollEquals(poll) - .addNull(VoterList.PROPERTY_PARENT) - .findUniqueOrNull(); - - List<VoterListMember> allMembers = getVoterListDao().getAllMembers(mainVoterList); - allMembers.stream() - .map(VoterListMember::getMember) - .distinct() - .forEach(pollenPrincipal -> { - RestrictedPollInvitationEmail mail = emailService.newRestrictedPollInvitationEmail(poll, pollenPrincipal); - mail.addTo(pollenPrincipal.getEmail()); - emailService.send(mail); - }); - } commit(); } @@ -332,7 +314,7 @@ public class NotificationService extends PollenServiceSupport { } } - public void onAddVoterList(Poll poll, List<VoterListMember> voterListMembers) { + public void sendInvitation(Poll poll, List<VoterListMember> voterListMembers) { EmailService emailService = getEmailService(); voterListMembers.stream() diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/service/PollService.java b/pollen-services/src/main/java/org/chorem/pollen/services/service/PollService.java index 1e48cad2..57c8c4f8 100644 --- a/pollen-services/src/main/java/org/chorem/pollen/services/service/PollService.java +++ b/pollen-services/src/main/java/org/chorem/pollen/services/service/PollService.java @@ -175,6 +175,8 @@ public class PollService extends PollenServiceSupport { if (Polls.isPollRestricted(entity)) { long participantCount = getVoterListService().getVoterListMemberCount(entity); bean.setParticipantCount(participantCount); + long participantInvitedCount = getVoterListService().getVoterListMemberInvitedCount(entity); + bean.setParticipantInvitedCount(participantInvitedCount); } long choiceCount = getChoiceService().getChoiceCount(entity); bean.setChoiceCount(choiceCount); diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/service/VoterListService.java b/pollen-services/src/main/java/org/chorem/pollen/services/service/VoterListService.java index 01f118ac..cb870f25 100644 --- a/pollen-services/src/main/java/org/chorem/pollen/services/service/VoterListService.java +++ b/pollen-services/src/main/java/org/chorem/pollen/services/service/VoterListService.java @@ -67,6 +67,7 @@ public class VoterListService extends PollenServiceSupport { } bean.setWeight(entity.getWeight()); bean.getVoterListId().setEntityId(entity.getVoterList().getTopiaId()); + bean.setInvitationSent(entity.isInvitationSent()); boolean voting = getVoteDao().forVoterListMemberContains(entity).exists(); bean.setVoting(voting); @@ -549,7 +550,7 @@ public class VoterListService extends PollenServiceSupport { } - List<VoterListMember> newVoters = createVoters(poll, listsToSave, membersToSave); + createVoters(poll, listsToSave, membersToSave); for (VoterList voterList : voterListToDelete) { @@ -565,8 +566,6 @@ public class VoterListService extends PollenServiceSupport { commit(); - getNotificationService().onAddVoterList(poll, newVoters); - } protected void checkVoters(Poll poll, List<VoterListBean> listsToSave, List<VoterListMemberBean> membersToSave) throws InvalidFormException { @@ -677,6 +676,15 @@ public class VoterListService extends PollenServiceSupport { List<VoterListMember> newVoters = Lists.newLinkedList(); + List<PollenPrincipal> principalSentInvitation = getVoterListMemberDao() + .forProperties(VoterListMember.PROPERTY_VOTER_LIST + "." + VoterList.PROPERTY_POLL, poll) + .addEquals(VoterListMember.PROPERTY_INVITATION_SENT, true) + .findAll() + .stream() + .map(VoterListMember::getMember) + .collect(Collectors.toList()); + + for (VoterListBean voterList : listsToSave) { if (voterList.getEntityId() == null || voterList.isTemporaryId()) { @@ -708,6 +716,9 @@ public class VoterListService extends PollenServiceSupport { voterListMember.setEntityId(null); VoterListMember voterListMemberSaved = saveVoterListMember(poll, voterListMember); voterListMember.setEntityId(voterListMemberSaved.getTopiaId()); + if (principalSentInvitation.contains(voterListMemberSaved.getMember())) { + voterListMemberSaved.setInvitationSent(true); + } newVoters.add(voterListMemberSaved); } else { @@ -718,7 +729,7 @@ public class VoterListService extends PollenServiceSupport { return newVoters; } - public int resendInvitationVoterList(String pollId, String voterListId) { + public int sendInvitationVoterList(String pollId, String voterListId, boolean allMemberNoVoting) { checkIsConnectedRequired(); checkNotNull(pollId); @@ -730,10 +741,10 @@ public class VoterListService extends PollenServiceSupport { List<VoterListMember> members = getVoterListDao().getAllMembers(voterList); - return resendInvitation(poll, members); + return sendInvitation(poll, members, allMemberNoVoting); } - public boolean resendInvitationMember(String pollId, String voterListId, String memberId) { + public boolean sendInvitationMember(String pollId, String voterListId, String memberId, boolean allMemberNoVoting) { checkIsConnectedRequired(); checkNotNull(pollId); @@ -744,30 +755,52 @@ public class VoterListService extends PollenServiceSupport { VoterListMember member = getVoterListMember0(voterList, memberId); - return resendInvitation(poll, Collections.singletonList(member)) == 1; + return sendInvitation(poll, Collections.singletonList(member), allMemberNoVoting) == 1; } - protected int resendInvitation(Poll poll, List<VoterListMember> members) { + protected int sendInvitation(Poll poll, List<VoterListMember> members, boolean allMemberNoVoting) { List<Vote> votes = getVoteDao().forPollEquals(poll).findAll(); - final Set<VoterListMember> memberVoting = votes.stream() - .map(Vote::getVoterListMember) - .flatMap(Collection::stream) - .collect(Collectors.toSet()); + List<VoterListMember> memberToSend; - List<VoterListMember> memberToSend = members.stream() - .filter(member -> !memberVoting.contains(member)) - .collect(Collectors.toList()); + if (allMemberNoVoting) { - getNotificationService().onAddVoterList(poll, memberToSend); + final Set<VoterListMember> memberVoting = votes.stream() + .map(Vote::getVoterListMember) + .flatMap(Collection::stream) + .collect(Collectors.toSet()); + + memberToSend = members.stream() + .filter(member -> !memberVoting.contains(member)) + .collect(Collectors.toList()); + } else { + memberToSend = members.stream() + .filter(member -> ! member.isInvitationSent()) + .collect(Collectors.toList()); + } + + getNotificationService().sendInvitation(poll, memberToSend); + + // plusieurs membre dans des liste différent peuvent avoir le même email + List<PollenPrincipal> pollenPrincipals = memberToSend.stream().map(VoterListMember::getMember).collect(Collectors.toList()); + + getVoterListMemberDao() + .forProperties(VoterListMember.PROPERTY_VOTER_LIST + "." + VoterList.PROPERTY_POLL, poll) + .addIn(VoterListMember.PROPERTY_MEMBER, pollenPrincipals) + .findAll() + .forEach(m -> m.setInvitationSent(true)); + + commit(); return memberToSend.size(); } public long getVoterListMemberCount(Poll poll) { - return getVoterListMemberDao() - .forProperties(VoterListMember.PROPERTY_VOTER_LIST + "." + VoterList.PROPERTY_POLL, poll) - .count(); + return getVoterListMemberDao().countDistinctMembers(poll, false); + } + + public long getVoterListMemberInvitedCount(Poll poll) { + return getVoterListMemberDao().countDistinctMembers(poll, true); } public Set<String> getVoterListMemberMails(VoterList voterList) { diff --git a/pollen-ui-riot-js/src/main/web/i18n/en.json b/pollen-ui-riot-js/src/main/web/i18n/en.json index c37ddfe1..15f8c500 100644 --- a/pollen-ui-riot-js/src/main/web/i18n/en.json +++ b/pollen-ui-riot-js/src/main/web/i18n/en.json @@ -31,7 +31,14 @@ "summary_invitations": "Number of invitations to vote sent by email:", "summary_vote": "Vote", "summary_members": "Participants", - "summary_membersNb": "participants received an email with a link to vote.", + "summary_membersInvited": "participants received an email with a link to vote.", + "summary_membersNoInvited_all": "Invitation emails have not been sent yet", + "summary_membersNoInvited_many": "{0} invitation emails have not been sent yet", + "summary_membersNoInvited_one": "1 Invitation email has not been sent yet", + "summary_sendInvitation": "Send invitation", + "summary_sendInvitations": "Send {0} invitations", + "summary_sendInvitations_success": "The {0} invitations are sent", + "summary_sendInvitation_success": "The invitation is sent", "summary_closePoll": "Close poll", "summary_reopenPoll": "Reopen poll", "summary_clonePoll": "Clone poll", diff --git a/pollen-ui-riot-js/src/main/web/i18n/fr.json b/pollen-ui-riot-js/src/main/web/i18n/fr.json index 3ac0d4a0..6208ddb0 100644 --- a/pollen-ui-riot-js/src/main/web/i18n/fr.json +++ b/pollen-ui-riot-js/src/main/web/i18n/fr.json @@ -31,7 +31,14 @@ "summary_invitations": "Nombre d'invitations à voter envoyées par email:", "summary_vote": "Voter", "summary_members": "Participants", - "summary_membersNb": "participants ont reçu un email avec un lien pour voter.", + "summary_membersInvited": "participants ont reçu un email avec un lien pour voter.", + "summary_membersNoInvited_all": "Les mails d'invitations n'ont pas encore été envoyés", + "summary_membersNoInvited_many": "{0} mails d'invitation n'ont pas encore été envoyés", + "summary_membersNoInvited_one": "1 mails d'invitation n'a pas encore été envoyé", + "summary_sendInvitation": "Envoyer l'invitation", + "summary_sendInvitations": "Envoyer les {0} invitations", + "summary_sendInvitations_success": "Les {0} invitations sont envoyées", + "summary_sendInvitation_success": "L'invitation est envoyée", "summary_closePoll": "Clôturer le sondage", "summary_reopenPoll": "Réouvrir le sondage", "summary_clonePoll": "Cloner le sondage", diff --git a/pollen-ui-riot-js/src/main/web/js/PollForm.js b/pollen-ui-riot-js/src/main/web/js/PollForm.js index 1e87823d..52c38fb4 100644 --- a/pollen-ui-riot-js/src/main/web/js/PollForm.js +++ b/pollen-ui-riot-js/src/main/web/js/PollForm.js @@ -214,7 +214,8 @@ class PollForm { if (this.model.pollType !== "FREE") { promises.push(voterListService.save()); } - return Promise.all(promises); + return Promise.all(promises) + .then(() => this.loadPoll(this.model.id, this.model.permissions)); } previousStep() { @@ -334,6 +335,23 @@ class PollForm { return Promise.reject("Init poll after get invalid emails"); } + sendInvitations() { + if (this.model.id) { + if (this.model.pollType === "RESTRICTED" && this.mainVoterList) { + return voterListService.sendInvitationList(this.mainVoterList) + .then(nbInvitation => { + return pollService.getPoll(this.model.id, this.model.permission) + .then(poll => { + Object.assign(this.model, poll); + return nbInvitation; + }); + }); + } + return Promise.reject("send invitation only for restricted poll"); + } + return Promise.reject("Init poll after get invalid emails"); + } + } export default singleton(PollForm); diff --git a/pollen-ui-riot-js/src/main/web/js/VoterListService.js b/pollen-ui-riot-js/src/main/web/js/VoterListService.js index 452bd878..3c9ce377 100644 --- a/pollen-ui-riot-js/src/main/web/js/VoterListService.js +++ b/pollen-ui-riot-js/src/main/web/js/VoterListService.js @@ -167,11 +167,11 @@ class VoterListService extends FetchService { let index = parent.subLists.indexOf(voterList); parent.subLists.splice(index, 1); - voterList.subLists.forEach(subList => { + voterList.subLists && voterList.subLists.forEach(subList => { this._deleteVoterList2(subList); }); - voterList.members.forEach(member => { + voterList.members && voterList.members.forEach(member => { delete this.voterListMembersById[member.id]; }); @@ -337,6 +337,22 @@ class VoterListService extends FetchService { return Promise.all(importPromises); } + sendInvitationList(voterList) { + if (!voterList.temp) { + let url = this._getUrlPrefix(this.pollForm.model.id, voterList.id) + "/send"; + return this.get(url, {permission: this.pollForm.model.permission}); + } + return Promise.reject(); + } + + sendInvitationMember(member) { + if (!member.temp) { + let url = this._getUrlPrefix(this.pollForm.model.id, member.voterListId) + "/members/" + member.id + "/send"; + return this.get(url, {permission: this.pollForm.model.permission}); + } + return Promise.reject(); + } + resendInvitationList(voterList) { if (!voterList.temp) { let url = this._getUrlPrefix(this.pollForm.model.id, voterList.id) + "/resend"; diff --git a/pollen-ui-riot-js/src/main/web/tag/poll/Summary.tag.html b/pollen-ui-riot-js/src/main/web/tag/poll/Summary.tag.html index f26c5f90..01ae48a3 100644 --- a/pollen-ui-riot-js/src/main/web/tag/poll/Summary.tag.html +++ b/pollen-ui-riot-js/src/main/web/tag/poll/Summary.tag.html @@ -18,11 +18,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #L% --> -import "./Choices.tag.html"; -import "./Settings.tag.html"; -import "../popup/QrCodeButton.tag.html"; -import "../components/MultiLineLabel.tag.html"; - <Summary> <div if={successMessage} class="c-alert c-alert--success">{successMessage}</div> @@ -74,7 +69,7 @@ import "../components/MultiLineLabel.tag.html"; <label class="c-label" for="voteUrl"> {_t.shareLink} </label> - <div class="share-actions"> + <div class="summary-part-actions"> <div class="c-input-group"> <div class="o-field"> <input id="voteUrl" @@ -103,8 +98,22 @@ import "../components/MultiLineLabel.tag.html"; <div if={opts.form.model.pollType === "RESTRICTED"} class="summary-part"> <h3>{_t.members}</h3> - <div> - <strong>{opts.form.model.participantCount}</strong> {_t.membersNb} + <div if={opts.form.model.participantInvitedCount == opts.form.model.participantCount}> + <strong>{opts.form.model.participantCount}</strong> {_t.membersInvited} + </div> + <div if={opts.form.model.participantInvitedCount < opts.form.model.participantCount}> + <strong>{opts.form.model.participantCount}</strong> {_t.members} + <span class="invitations-warning c-badge c-badge--warning"> + {getMembersWarningLabel()} + </span> + <div class="summary-part-actions"> + <button type="button" + class="c-button c-button--info" + onclick={sendInvitations}> + <i class="fa fa-paper-plane" aria-hidden="true"></i> + {getSendInvitationsLabel()} + </button> + </div> </div> </div> @@ -138,6 +147,11 @@ import "../components/MultiLineLabel.tag.html"; </div> <script type="es6"> + import "./Choices.tag.html"; + import "./Settings.tag.html"; + import "../popup/QrCodeButton.tag.html"; + import "../components/MultiLineLabel.tag.html"; + import session from "../../js/Session"; this.session = session; @@ -148,6 +162,32 @@ import "../components/MultiLineLabel.tag.html"; this.voteUrl = window.location.origin + window.location.pathname + "#poll/" + this.opts.form.model.id + "/vote"; }); + this.getMembersWarningLabel = () => { + let label; + if (this.opts.form.model.participantInvitedCount === 0) { + label = this._t.membersNoInvited_all; + } else { + let noInvited = this.opts.form.model.participantCount - this.opts.form.model.participantInvitedCount; + if (noInvited > 1) { + label = this._l("membersNoInvited_many", noInvited); + } else { + label = this._t.membersNoInvited_one; + } + } + return label; + }; + + this.getSendInvitationsLabel = () => { + let label; + let noInvited = this.opts.form.model.participantCount - this.opts.form.model.participantInvitedCount; + if (noInvited > 1) { + label = this._l("sendInvitations", noInvited); + } else { + label = this._t.sendInvitation; + } + return label; + }; + this.copyUrl = (refInputUrl) => () => { this.refs[refInputUrl].select(); document.execCommand("copy"); @@ -179,6 +219,15 @@ import "../components/MultiLineLabel.tag.html"; document.execCommand("copy"); }; + this.sendInvitations = () => { + this.opts.form.sendInvitations() + .then(nbInvitation => { + let message = nbInvitation > 1 ? this._l("sendInvitations_success", nbInvitation) : this._t.sendInvitation_success; + this.bus.trigger("message", message, "info"); + this.update(); + }); + }; + </script> <style> @@ -192,17 +241,22 @@ import "../components/MultiLineLabel.tag.html"; background-color: #eee; } - .share-actions { + .summary-part-actions { + margin-top: 5px; display: flex; } - .share-actions > .c-input-group { + .summary-part-actions > .c-input-group { flex-grow: 0.5; } - .share-actions > * { + .summary-part-actions > * { margin-right: 5px; } + .invitations-warning { + font-size: 1em; + } + </style> </Summary> -- To stop receiving notification emails like this one, please contact chorem.org SCM administrator <admin+scm@chorem.org>.