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 719bffdf9935808be4f67150c815816d5f26bc2e Author: Sylvain Bavencoff <bavencoff@codelutin.com> Date: Tue Apr 18 12:15:10 2017 +0200 liste de favoris : ajout du poids sur le membre et ajout de sous-liste dans les services --- .../entity/ChildFavoriteListTopiaDao.java | 32 ++++ pollen-persistence/src/main/xmi/pollen.zargo | Bin 21426 -> 23829 bytes .../chorem/pollen/rest/api/v1/FavoriteListApi.java | 32 ++++ pollen-rest-api/src/main/resources/mapping | 5 + .../services/bean/ChildFavoriteListBean.java | 56 +++++++ .../services/bean/FavoriteListMemberBean.java | 11 ++ .../service/FavoriteListImportFromFile.java | 44 +++-- .../service/FavoriteListImportFromLdap.java | 22 +++ .../services/service/FavoriteListService.java | 179 +++++++++++++++++++++ .../services/service/PollenServiceSupport.java | 5 + .../i18n/pollen-services_en_GB.properties | 6 + .../i18n/pollen-services_fr_FR.properties | 6 + .../services/service/FavoriteListServiceTest.java | 101 +++++++++++- pollen-ui-riot-js/src/main/web/i18n.json | 14 +- .../web/tag/favoriteList/FavoriteList.tag.html | 52 ++++-- .../main/web/tag/favoriteList/MemberCard.tag.html | 15 +- 16 files changed, 543 insertions(+), 37 deletions(-) diff --git a/pollen-persistence/src/main/java/org/chorem/pollen/persistence/entity/ChildFavoriteListTopiaDao.java b/pollen-persistence/src/main/java/org/chorem/pollen/persistence/entity/ChildFavoriteListTopiaDao.java new file mode 100644 index 0000000..3e7d9fa --- /dev/null +++ b/pollen-persistence/src/main/java/org/chorem/pollen/persistence/entity/ChildFavoriteListTopiaDao.java @@ -0,0 +1,32 @@ +package org.chorem.pollen.persistence.entity; + + +import java.util.List; + +public class ChildFavoriteListTopiaDao extends AbstractChildFavoriteListTopiaDao<ChildFavoriteList> { + + public boolean isAncestorOrSelf(String ancestorFavoriteListId, String favoriteListId) { + + boolean result = ancestorFavoriteListId.equals(favoriteListId); + + if (! result) { + + List<ChildFavoriteList> childrenFavoriteList = forProperties(ChildFavoriteList.PROPERTY_CHILD + "." + FavoriteList.PROPERTY_TOPIA_ID, favoriteListId).findAll(); + + for (ChildFavoriteList childFavoriteList : childrenFavoriteList) { + + result = result || isAncestorOrSelf(ancestorFavoriteListId, childFavoriteList.getParent().getTopiaId()); + + if (result) { + break; + } + + } + } + + return result; + + } + + +} //ChildFavoriteListTopiaDao diff --git a/pollen-persistence/src/main/xmi/pollen.zargo b/pollen-persistence/src/main/xmi/pollen.zargo index b2357c4..8676954 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/FavoriteListApi.java b/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/FavoriteListApi.java index 50b381f..b156b0b 100644 --- a/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/FavoriteListApi.java +++ b/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/FavoriteListApi.java @@ -21,8 +21,10 @@ package org.chorem.pollen.rest.api.v1; * #L% */ +import org.chorem.pollen.persistence.entity.ChildFavoriteList; import org.chorem.pollen.persistence.entity.FavoriteList; import org.chorem.pollen.persistence.entity.FavoriteListMember; +import org.chorem.pollen.services.bean.ChildFavoriteListBean; import org.chorem.pollen.services.bean.FavoriteListBean; import org.chorem.pollen.services.bean.FavoriteListMemberBean; import org.chorem.pollen.services.bean.PaginationParameterBean; @@ -114,4 +116,34 @@ public class FavoriteListApi extends WebMotionController { favoriteListService.deleteFavoriteListMember(favoriteListId.getEntityId(), memberId.getEntityId()); } + + public PaginationResultBean<ChildFavoriteListBean> getChildrenLists(FavoriteListService favoriteListService, PollenEntityId<FavoriteList> favoriteListId, PaginationParameterBean paginationParameter) { + + return favoriteListService.getChildrenLists(favoriteListId.getEntityId(), paginationParameter); + + } + + public ChildFavoriteListBean getChildList(FavoriteListService favoriteListService, PollenEntityId<FavoriteList> favoriteListId, PollenEntityId<ChildFavoriteList> childListId) { + + return favoriteListService.getChildList(favoriteListId.getEntityId(), childListId.getEntityId()); + + } + + public PollenEntityRef<ChildFavoriteList> addChildList(FavoriteListService favoriteListService, PollenEntityId<FavoriteList> favoriteListId, ChildFavoriteListBean childList) throws InvalidFormException { + + return favoriteListService.addChildList(favoriteListId.getEntityId(), childList); + + } + + public ChildFavoriteListBean editChildList(FavoriteListService favoriteListService, PollenEntityId<FavoriteList> favoriteListId, ChildFavoriteListBean childList) throws InvalidFormException { + + return favoriteListService.editChildList(favoriteListId.getEntityId(), childList); + + } + + public void removeChildList(FavoriteListService favoriteListService, PollenEntityId<FavoriteList> favoriteListId, PollenEntityId<ChildFavoriteList> childListId) { + + favoriteListService.removeChildList(favoriteListId.getEntityId(), childListId.getEntityId()); + + } } diff --git a/pollen-rest-api/src/main/resources/mapping b/pollen-rest-api/src/main/resources/mapping index 8dbf62f..6666858 100644 --- a/pollen-rest-api/src/main/resources/mapping +++ b/pollen-rest-api/src/main/resources/mapping @@ -92,6 +92,11 @@ GET /v1/favoriteLists/{favoriteListId}/members/{memberId} FavoriteListApi. POST /v1/favoriteLists/{favoriteListId}/members FavoriteListApi.addMember PUT,POST /v1/favoriteLists/{favoriteListId}/members/{memberId} FavoriteListApi.editMember DELETE /v1/favoriteLists/{favoriteListId}/members/{memberId} FavoriteListApi.removeMember +GET /v1/favoriteLists/{favoriteListId}/lists FavoriteListApi.getChildrenLists +GET /v1/favoriteLists/{favoriteListId}/lists/{childListId} FavoriteListApi.getChildList +POST /v1/favoriteLists/{favoriteListId}/lists FavoriteListApi.addChildList +PUT,POST /v1/favoriteLists/{favoriteListId}/lists/{childListId} FavoriteListApi.editChildList +DELETE /v1/favoriteLists/{favoriteListId}/lists/{childListId} FavoriteListApi.removeChildList # PollApi diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/bean/ChildFavoriteListBean.java b/pollen-services/src/main/java/org/chorem/pollen/services/bean/ChildFavoriteListBean.java new file mode 100644 index 0000000..fc77669 --- /dev/null +++ b/pollen-services/src/main/java/org/chorem/pollen/services/bean/ChildFavoriteListBean.java @@ -0,0 +1,56 @@ +package org.chorem.pollen.services.bean; + +import org.chorem.pollen.persistence.entity.ChildFavoriteList; +import org.chorem.pollen.persistence.entity.ChildFavoriteListImpl; + +/** + * @author Sylvain Bavencoff - bavencoff@codelutin.com + */ +public class ChildFavoriteListBean extends PollenBean<ChildFavoriteList> { + + protected FavoriteListBean child; + + protected double weight; + + public ChildFavoriteListBean() { + super(ChildFavoriteList.class); + } + + @Override + public void fromEntity(ChildFavoriteList entity) { + + setEntityId(entity.getTopiaId()); + FavoriteListBean child = new FavoriteListBean(); + child.fromEntity(entity.getChild()); + setChild(child); + setWeight(entity.getWeight()); + + + } + + @Override + public ChildFavoriteList toEntity() { + + ChildFavoriteList entity = new ChildFavoriteListImpl(); + entity.setWeight(getWeight()); + + return entity; + + } + + public FavoriteListBean getChild() { + return child; + } + + public void setChild(FavoriteListBean child) { + this.child = child; + } + + public double getWeight() { + return weight; + } + + public void setWeight(double weight) { + this.weight = weight; + } +} diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/bean/FavoriteListMemberBean.java b/pollen-services/src/main/java/org/chorem/pollen/services/bean/FavoriteListMemberBean.java index f19a990..1af9bcb 100644 --- a/pollen-services/src/main/java/org/chorem/pollen/services/bean/FavoriteListMemberBean.java +++ b/pollen-services/src/main/java/org/chorem/pollen/services/bean/FavoriteListMemberBean.java @@ -36,6 +36,8 @@ public class FavoriteListMemberBean extends PollenBean<FavoriteListMember> { protected String email; + protected double weight; + public FavoriteListMemberBean() { super(FavoriteListMember.class); } @@ -46,6 +48,7 @@ public class FavoriteListMemberBean extends PollenBean<FavoriteListMember> { setEntityId(entity.getTopiaId()); setName(entity.getName()); setEmail(entity.getEmail()); + setWeight(entity.getWeight()); } @@ -55,6 +58,7 @@ public class FavoriteListMemberBean extends PollenBean<FavoriteListMember> { FavoriteListMember entity = new FavoriteListMemberImpl(); entity.setEmail(getEmail()); entity.setName(getName()); + entity.setWeight(getWeight()); return entity; @@ -77,4 +81,11 @@ public class FavoriteListMemberBean extends PollenBean<FavoriteListMember> { this.email = email; } + public double getWeight() { + return weight; + } + + public void setWeight(double weight) { + this.weight = weight; + } } diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/service/FavoriteListImportFromFile.java b/pollen-services/src/main/java/org/chorem/pollen/services/service/FavoriteListImportFromFile.java index 9038344..9ca4939 100644 --- a/pollen-services/src/main/java/org/chorem/pollen/services/service/FavoriteListImportFromFile.java +++ b/pollen-services/src/main/java/org/chorem/pollen/services/service/FavoriteListImportFromFile.java @@ -101,24 +101,49 @@ public class FavoriteListImportFromFile extends PollenServiceSupport implements } lineNumber++; - int spaceIndex = line.indexOf(' '); + String[] columns = line.split(";"); + + String email; String memberName; + double weight; - if (spaceIndex == -1) { + if (columns.length >= 1) { // only email - email = line; - memberName = line; + email = columns[0].trim(); - } else { + if (columns.length >= 2) { + + memberName = columns[1].trim(); + + if (columns.length >= 3) { + + try { + weight = Double.parseDouble(columns[2].trim()); + } catch (NumberFormatException e) { + String error = l(locale, "pollen.error.favoriteList.import.csv.weight.notNumber", lineNumber, columns[2].trim()); + throw new FavoriteListImportException(error, null); + } + + } else { - // email + name - email = line.substring(0, spaceIndex); - memberName = line.substring(spaceIndex); + weight = 1; + } + + } else { + + memberName = columns[0].trim(); + weight = 1; + + } + + } else { + + continue; + } - memberName = memberName.trim(); if (!usedName.add(memberName)) { // name already exists @@ -146,6 +171,7 @@ public class FavoriteListImportFromFile extends PollenServiceSupport implements FavoriteListMember member = getFavoriteListMemberDao().create(); member.setName(memberName); member.setEmail(email); + member.setWeight(weight); member.setFavoriteList(favoriteList); if (log.isDebugEnabled()) { diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/service/FavoriteListImportFromLdap.java b/pollen-services/src/main/java/org/chorem/pollen/services/service/FavoriteListImportFromLdap.java index 0b14b49..c2434ec 100644 --- a/pollen-services/src/main/java/org/chorem/pollen/services/service/FavoriteListImportFromLdap.java +++ b/pollen-services/src/main/java/org/chorem/pollen/services/service/FavoriteListImportFromLdap.java @@ -29,6 +29,7 @@ import org.chorem.pollen.persistence.entity.FavoriteList; import org.chorem.pollen.persistence.entity.FavoriteListMember; import org.nuiton.util.StringUtil; +import javax.naming.Context; import javax.naming.NamingEnumeration; import javax.naming.NamingException; import javax.naming.directory.Attribute; @@ -36,10 +37,14 @@ import javax.naming.directory.DirContext; import javax.naming.directory.InitialDirContext; import javax.naming.directory.SearchControls; import javax.naming.directory.SearchResult; +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; import java.util.List; import java.util.Locale; import java.util.Properties; import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import static org.nuiton.i18n.I18n.l; @@ -85,6 +90,20 @@ public class FavoriteListImportFromLdap extends PollenServiceSupport implements // Initialisation du contexte Properties env = new Properties(); + Pattern loginLdapPattern = Pattern.compile("ldaps?://(([^:]+):([^@]+)@)?.*"); + Matcher matcher = loginLdapPattern.matcher(ldap); + if (matcher.find() && matcher.group(1) != null) { + if (matcher.group(2) != null) { + String login = URLDecoder.decode(matcher.group(2), "UTF-8"); + env.put(Context.SECURITY_PRINCIPAL, login); + } + if (matcher.group(3) != null) { + String password = URLDecoder.decode(matcher.group(3), "UTF-8"); + env.put(Context.SECURITY_CREDENTIALS, password); + } + ldap = ldap.replace(matcher.group(1), ""); + } + DirContext ictx = new InitialDirContext(env); // Recherche en profondeur @@ -134,6 +153,7 @@ public class FavoriteListImportFromLdap extends PollenServiceSupport implements FavoriteListMember member = getFavoriteListMemberDao().create(); member.setName(memberName); member.setEmail(email); + member.setWeight(1); member.setFavoriteList(favoriteList); if (log.isDebugEnabled()) { @@ -147,6 +167,8 @@ public class FavoriteListImportFromLdap extends PollenServiceSupport implements throw new FavoriteListImportException("LDAP", ex); + } catch (UnsupportedEncodingException e) { + throw new FavoriteListImportException("LDAP", e); } commit(); diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/service/FavoriteListService.java b/pollen-services/src/main/java/org/chorem/pollen/services/service/FavoriteListService.java index 03d0634..8ac2b24 100644 --- a/pollen-services/src/main/java/org/chorem/pollen/services/service/FavoriteListService.java +++ b/pollen-services/src/main/java/org/chorem/pollen/services/service/FavoriteListService.java @@ -24,11 +24,13 @@ package org.chorem.pollen.services.service; import com.google.common.collect.Sets; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; +import org.chorem.pollen.persistence.entity.ChildFavoriteList; import org.chorem.pollen.persistence.entity.FavoriteList; import org.chorem.pollen.persistence.entity.FavoriteListMember; import org.chorem.pollen.persistence.entity.FavoriteListMemberTopiaDao; import org.chorem.pollen.persistence.entity.FavoriteListTopiaDao; import org.chorem.pollen.persistence.entity.PollenUser; +import org.chorem.pollen.services.bean.ChildFavoriteListBean; import org.chorem.pollen.services.bean.FavoriteListBean; import org.chorem.pollen.services.bean.FavoriteListMemberBean; import org.chorem.pollen.services.bean.PaginationParameterBean; @@ -39,6 +41,7 @@ import org.nuiton.util.pagination.PaginationResult; import java.io.File; import java.util.List; +import java.util.Optional; import java.util.Set; import static org.nuiton.i18n.I18n.l; @@ -357,10 +360,33 @@ public class FavoriteListService extends PollenServiceSupport { toSave.setName(favoriteListMember.getName()); toSave.setEmail(getCleanMail(favoriteListMember.getEmail())); + toSave.setWeight(favoriteListMember.getWeight()); return toSave; } + protected ChildFavoriteList getChildList0(FavoriteList parentList, String childListId) { + + ChildFavoriteList result = getChildFavoriteListDao().forTopiaIdEquals(childListId).findUnique(); + + if (!parentList.equals(result.getParent())) { + + throw new InvalidEntityLinkException(ChildFavoriteList.PROPERTY_PARENT, parentList, result); + + } + + return result; + + } + + protected List<ChildFavoriteList> getChildrenLists0(FavoriteList parentList) { + + List<ChildFavoriteList> result = getChildFavoriteListDao().forParentEquals(parentList).findAll(); + + return result; + + } + protected ErrorMap checkFavoriteList(List<FavoriteList> existingFavoriteLists, FavoriteListBean favoriteList) { ErrorMap errors = new ErrorMap(); @@ -454,10 +480,46 @@ public class FavoriteListService extends PollenServiceSupport { } + check(errors, "weight", favoriteListMember.getWeight() > 0, l(getLocale(), "pollen.error.favoriteListMember.weight.negativeOrNull")); + return errors; } + protected ErrorMap checkChildList(FavoriteList parentList, List<ChildFavoriteList> existingChildList, ChildFavoriteListBean childFavoriteList) { + + ErrorMap errors = new ErrorMap(); + + boolean childListExists = childFavoriteList.isPersisted(); + + if (!childListExists && CollectionUtils.isNotEmpty(existingChildList)) { + + // get all used + Optional<String> childListAlreadyExist = existingChildList.stream() + .map(ChildFavoriteList::getChild) + .map(FavoriteList::getTopiaId) + .filter(id -> id.equals(childFavoriteList.getChild().getEntityId())) + .findFirst(); + + check(errors, ChildFavoriteList.PROPERTY_CHILD, + !childListAlreadyExist.isPresent(), + l(getLocale(), "pollen.error.childFavoriteList.already.used")); + } + + check(errors, ChildFavoriteList.PROPERTY_CHILD, + !parentList.getTopiaId().equals(childFavoriteList.getChild().getEntityId()), + l(getLocale(), "pollen.error.childFavoriteList.sameParentChild", parentList.getName())); + + check(errors, ChildFavoriteList.PROPERTY_CHILD, + !getChildFavoriteListDao().isAncestorOrSelf(childFavoriteList.getChild().getEntityId(), parentList.getTopiaId()), + l(getLocale(), "pollen.error.childFavoriteList.childIsAncestor", parentList.getName(), childFavoriteList.getChild().getName())); + + check(errors, "weight", childFavoriteList.getWeight() > 0, l(getLocale(), "pollen.error.childFavoriteList.weight.negativeOrNull")); + + + return errors; + } + protected PaginationParameter getFavoriteListPaginationParameter(PaginationParameterBean paginationParameter) { if (paginationParameter == null) { @@ -488,4 +550,121 @@ public class FavoriteListService extends PollenServiceSupport { } + public PaginationResultBean<ChildFavoriteListBean> getChildrenLists(String favoriteListId, PaginationParameterBean paginationParameter) { + + checkIsConnected(); + checkNotNull(favoriteListId); + + PollenUser user = getConnectedUser(); + + FavoriteList favoriteList = getFavoriteList0(user, favoriteListId); + + PaginationParameter page = getFavoriteListPaginationParameter(paginationParameter); + + PaginationResult<ChildFavoriteList> children = getChildFavoriteListDao().forParentEquals(favoriteList).findPage(page); + return toPaginationListBean(ChildFavoriteListBean.class, children); + + } + + public ChildFavoriteListBean getChildList(String favoriteListId, String childListId) { + + checkIsConnected(); + checkNotNull(favoriteListId); + checkNotNull(childListId); + + PollenUser user = getConnectedUser(); + + FavoriteList favoriteList = getFavoriteList0(user, favoriteListId); + + ChildFavoriteList child = getChildList0(favoriteList, childListId); + return toBean(ChildFavoriteListBean.class, child); + + } + + public PollenEntityRef<ChildFavoriteList> addChildList(String favoriteListId, ChildFavoriteListBean childList) throws InvalidFormException { + + checkIsConnected(); + checkNotNull(favoriteListId); + checkNotNull(childList); + checkIsNotPersisted(childList); + + PollenUser user = getConnectedUser(); + + FavoriteList favoriteList = getFavoriteList0(user, favoriteListId); + + List<ChildFavoriteList> existingChildFavoriteList = getChildrenLists0(favoriteList); + + ErrorMap errorMap = checkChildList(favoriteList, existingChildFavoriteList, childList); + errorMap.failIfNotEmpty(); + + ChildFavoriteList result = saveChildFavoriteList(favoriteList, childList); + commit(); + + return PollenEntityRef.of(result); + + } + + public ChildFavoriteListBean editChildList(String favoriteListId, ChildFavoriteListBean childList) throws InvalidFormException { + checkIsConnected(); + checkNotNull(favoriteListId); + checkNotNull(childList); + checkIsPersisted(childList); + + PollenUser user = getConnectedUser(); + + FavoriteList favoriteList = getFavoriteList0(user, favoriteListId); + + List<ChildFavoriteList> existingChildFavoriteList = getChildrenLists0(favoriteList); + + ErrorMap errorMap = checkChildList(favoriteList, existingChildFavoriteList, childList); + errorMap.failIfNotEmpty(); + + ChildFavoriteList result = saveChildFavoriteList(favoriteList, childList); + commit(); + + return toBean(ChildFavoriteListBean.class, result); + + } + + public void removeChildList(String favoriteListId, String childListId) { + checkIsConnected(); + checkNotNull(favoriteListId); + checkNotNull(childListId); + + PollenUser user = getConnectedUser(); + + FavoriteList favoriteList = getFavoriteList0(user, favoriteListId); + + ChildFavoriteList childFavoriteList = getChildList0(favoriteList, childListId); + + getChildFavoriteListDao().delete(childFavoriteList); + commit(); + + } + + protected ChildFavoriteList saveChildFavoriteList(FavoriteList favoriteList, ChildFavoriteListBean childList) { + + boolean persisted = childList.isPersisted(); + + ChildFavoriteList toSave; + + if (persisted) { + + // get existing favorite list + toSave = getChildList0(favoriteList, childList.getEntityId()); + + } else { + + // create a new favorite list + toSave = getChildFavoriteListDao().create(); + toSave.setParent(favoriteList); + FavoriteList child = getFavoriteList0(getConnectedUser(), childList.getChild().getEntityId()); + toSave.setChild(child); + + } + + toSave.setWeight(childList.getWeight()); + + return toSave; + } } diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/service/PollenServiceSupport.java b/pollen-services/src/main/java/org/chorem/pollen/services/service/PollenServiceSupport.java index 5b46c28..a076dbb 100644 --- a/pollen-services/src/main/java/org/chorem/pollen/services/service/PollenServiceSupport.java +++ b/pollen-services/src/main/java/org/chorem/pollen/services/service/PollenServiceSupport.java @@ -28,6 +28,7 @@ import com.google.common.collect.Multimap; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.chorem.pollen.persistence.PollenPersistenceContext; +import org.chorem.pollen.persistence.entity.ChildFavoriteListTopiaDao; import org.chorem.pollen.persistence.entity.ChoiceTopiaDao; import org.chorem.pollen.persistence.entity.CommentTopiaDao; import org.chorem.pollen.persistence.entity.FavoriteListMemberTopiaDao; @@ -180,6 +181,10 @@ public abstract class PollenServiceSupport implements PollenService { return getPersistenceContext().getFavoriteListMemberDao(); } + protected ChildFavoriteListTopiaDao getChildFavoriteListDao() { + return getPersistenceContext().getChildFavoriteListDao(); + } + protected PollTopiaDao getPollDao() { return getPersistenceContext().getPollDao(); } 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 98a96b8..400d411 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 @@ -29,6 +29,10 @@ pollen.configuration.uiUrlPollVote=Url to vote on a poll pollen.configuration.version=Application version pollen.configurqtion.uiUrlPollVoteEdit=Url to edit a vote on a poll pollen.configurqtion.uiUrlUserValidate=Url de validate user account +pollen.error.childFavoriteList.already.used=Child list is already used +pollen.error.childFavoriteList.childIsAncestor=Child list is ancestor of %s +pollen.error.childFavoriteList.sameParentChild=Child must be not equal to parent +pollen.error.childFavoriteList.weight.negativeOrNull=Weight must be positive pollen.error.choice.choiceDateEmpty=choice date can not be empty pollen.error.choice.choiceDateExist=choice date already used in this list pollen.error.choice.choiceDateInvalid=Date format %s is not valid @@ -40,6 +44,7 @@ pollen.error.comment.text.mandatory=text can not be empty pollen.error.favoriteList.import.csv.already.used.email=Line %s \: Email already used pollen.error.favoriteList.import.csv.already.used.name=Line %s \: Name already used pollen.error.favoriteList.import.csv.invalid.email=Line %s \: Invalid email +pollen.error.favoriteList.import.csv.weight.notNumber=Line %s \: weight is not a number pollen.error.favoriteList.import.ldap.already.used.email= pollen.error.favoriteList.import.ldap.already.used.name= pollen.error.favoriteList.import.ldap.invalid.email= @@ -50,6 +55,7 @@ pollen.error.favoriteListMember.email.empty=member email can not be empty pollen.error.favoriteListMember.email.invalid=member email is not valid pollen.error.favoriteListMember.name.already.used=member name already used pollen.error.favoriteListMember.name.empty=member name can not be empty +pollen.error.favoriteListMember.weight.negativeOrNull=Weight must be positive pollen.error.poll.beginChoiceDate.afterEndDate=the begin date of adding choice is after the end of poll pollen.error.poll.choice.mandatory=At least a choice is mandatory pollen.error.poll.choiceType.mandatory= 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 e03330f..b3e39a4 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 @@ -29,6 +29,10 @@ pollen.configuration.uiUrlPollVote=Url de vote sur un sondage pollen.configuration.version=Version de l'application pollen.configurqtion.uiUrlPollVoteEdit=Url d'édition de vote sur un sondage pollen.configurqtion.uiUrlUserValidate=Url de validation d'un compte utilisateur +pollen.error.childFavoriteList.already.used=La sous-liste est déjaà utlisée +pollen.error.childFavoriteList.childIsAncestor=La liste principal %s est déjà une sous-liste de %s +pollen.error.childFavoriteList.sameParentChild=La sous-lists ne peut pas être la liste principal +pollen.error.childFavoriteList.weight.negativeOrNull=le poids de la sous-liste doit être positif pollen.error.choice.choiceDateEmpty=La date ne peut pas être vide pollen.error.choice.choiceDateExist=La date exist déjà utilisé sur ce sondage pollen.error.choice.choiceDateInvalid=Le format de la date %s n'est pas valide @@ -40,6 +44,7 @@ pollen.error.comment.text.mandatory=le text est obligatoire pollen.error.favoriteList.import.csv.already.used.email=Ligne %s \: Courriel déjà utilisé pollen.error.favoriteList.import.csv.already.used.name=Ligne %s \: Nom déjà utilisé pollen.error.favoriteList.import.csv.invalid.email=Ligne %s \: Courriel invalide +pollen.error.favoriteList.import.csv.weight.notNumber=Ligne %s \: Le poids n'est pas un nombre pollen.error.favoriteList.import.ldap.already.used.email= pollen.error.favoriteList.import.ldap.already.used.name= pollen.error.favoriteList.import.ldap.invalid.email= @@ -50,6 +55,7 @@ pollen.error.favoriteListMember.email.empty=Le courriel est obligatoire pollen.error.favoriteListMember.email.invalid=Le courriel du membre est invalide pollen.error.favoriteListMember.name.already.used=Le nom du membre est déjà utilisé dans cette liste pollen.error.favoriteListMember.name.empty=Le nom du membre est obligatoire +pollen.error.favoriteListMember.weight.negativeOrNull=le poids du membre doit être positif pollen.error.poll.beginChoiceDate.afterEndDate=La date de début d'ajout de choix est après la date de fin du sondage pollen.error.poll.choice.mandatory=Au moins un choix est nécessaire pollen.error.poll.choiceType.mandatory= diff --git a/pollen-services/src/test/java/org/chorem/pollen/services/service/FavoriteListServiceTest.java b/pollen-services/src/test/java/org/chorem/pollen/services/service/FavoriteListServiceTest.java index 46caa21..9036181 100644 --- a/pollen-services/src/test/java/org/chorem/pollen/services/service/FavoriteListServiceTest.java +++ b/pollen-services/src/test/java/org/chorem/pollen/services/service/FavoriteListServiceTest.java @@ -27,6 +27,7 @@ import org.chorem.pollen.persistence.entity.FavoriteList; import org.chorem.pollen.persistence.entity.FavoriteListMember; import org.chorem.pollen.persistence.entity.PollenUser; import org.chorem.pollen.services.AbstractPollenServiceTest; +import org.chorem.pollen.services.bean.ChildFavoriteListBean; import org.chorem.pollen.services.bean.FavoriteListBean; import org.chorem.pollen.services.bean.FavoriteListMemberBean; import org.chorem.pollen.services.bean.PaginationParameterBean; @@ -70,7 +71,7 @@ public class FavoriteListServiceTest extends AbstractPollenServiceTest { user = application.fixture("user_jean"); } - public static String IMPORT_FILE_CONTENT = "user1@pollen.org user1\n" + + public static String IMPORT_FILE_CONTENT = "user1@pollen.org;user1\n" + "user2@pollen.org"; @Test @@ -134,7 +135,7 @@ public class FavoriteListServiceTest extends AbstractPollenServiceTest { } catch (InvalidFormException e) { // no name // no email - assertErrorKeyFound(e, "name", "email"); + assertErrorKeyFound(e, "name", "email", "weight"); } memberBean1.setName("member1"); @@ -143,7 +144,7 @@ public class FavoriteListServiceTest extends AbstractPollenServiceTest { Assert.fail(); } catch (InvalidFormException e) { // no email - assertErrorKeyFound(e, "email"); + assertErrorKeyFound(e, "email", "weight"); } memberBean1.setEmail("member1@"); @@ -152,10 +153,19 @@ public class FavoriteListServiceTest extends AbstractPollenServiceTest { Assert.fail(); } catch (InvalidFormException e) { // invalid email - assertErrorKeyFound(e, "email"); + assertErrorKeyFound(e, "email", "weight"); } memberBean1.setEmail("member1@pollen.org"); + try { + service.addFavoriteListMember(savedList1.getEntityId(), memberBean1); + Assert.fail(); + } catch (InvalidFormException e) { + // invalid email + assertErrorKeyFound(e, "weight"); + } + + memberBean1.setWeight(2); PollenEntityRef<FavoriteListMember> savedMmember1 = service.addFavoriteListMember(savedList1.getEntityId(), memberBean1); Assert.assertNotNull(savedMmember1); Assert.assertNotNull(savedMmember1.getEntityId()); @@ -166,6 +176,7 @@ public class FavoriteListServiceTest extends AbstractPollenServiceTest { memberBean2.setName("member1"); memberBean2.setEmail("member1@pollen.org"); + memberBean2.setWeight(1); try { service.addFavoriteListMember(savedList1.getEntityId(), memberBean2); Assert.fail(); @@ -229,6 +240,7 @@ public class FavoriteListServiceTest extends AbstractPollenServiceTest { FavoriteListMemberBean memberBean1 = new FavoriteListMemberBean(); memberBean1.setName("member1"); memberBean1.setEmail("member1@pollen.org"); + memberBean1.setWeight(1); PollenEntityRef<FavoriteListMember> savedMmember1 = service.addFavoriteListMember(savedList1.getEntityId(), memberBean1); Assert.assertNotNull(savedMmember1); Assert.assertNotNull(savedMmember1.getEntityId()); @@ -238,6 +250,7 @@ public class FavoriteListServiceTest extends AbstractPollenServiceTest { FavoriteListMemberBean memberBean2 = new FavoriteListMemberBean(); memberBean2.setName("member2"); memberBean2.setEmail("member2@pollen.org"); + memberBean2.setWeight(1); PollenEntityRef<FavoriteListMember> savedMmember2 = service.addFavoriteListMember(savedList1.getEntityId(), memberBean2); Assert.assertNotNull(savedMmember2); Assert.assertNotNull(savedMmember2.getEntityId()); @@ -296,6 +309,7 @@ public class FavoriteListServiceTest extends AbstractPollenServiceTest { FavoriteListMemberBean memberBean1 = new FavoriteListMemberBean(); memberBean1.setName("member1"); memberBean1.setEmail("member1@pollen.org"); + memberBean1.setWeight(1); PollenEntityRef<FavoriteListMember> savedMmember1 = service.addFavoriteListMember(savedList1.getEntityId(), memberBean1); Assert.assertNotNull(savedMmember1); Assert.assertNotNull(savedMmember1.getEntityId()); @@ -305,6 +319,7 @@ public class FavoriteListServiceTest extends AbstractPollenServiceTest { FavoriteListMemberBean memberBean2 = new FavoriteListMemberBean(); memberBean2.setName("member2"); memberBean2.setEmail("member2@pollen.org"); + memberBean2.setWeight(1); PollenEntityRef<FavoriteListMember> savedMmember2 = service.addFavoriteListMember(savedList1.getEntityId(), memberBean2); Assert.assertNotNull(savedMmember2); Assert.assertNotNull(savedMmember2.getEntityId()); @@ -324,13 +339,14 @@ public class FavoriteListServiceTest extends AbstractPollenServiceTest { memberBean1.setName("member2"); memberBean1.setEmail("member2[pollen.org"); + memberBean1.setWeight(0); try { service.editFavoriteListMember(savedList1.getEntityId(), memberBean1); Assert.fail(); } catch (InvalidFormException e) { // duplicated name // invalid email - assertErrorKeyFound(e, "name", "email"); + assertErrorKeyFound(e, "name", "email", "weight"); } memberBean1.setName("member3"); @@ -339,7 +355,7 @@ public class FavoriteListServiceTest extends AbstractPollenServiceTest { Assert.fail(); } catch (InvalidFormException e) { // invalid email - assertErrorKeyFound(e, "email"); + assertErrorKeyFound(e, "email", "weight"); } memberBean1.setEmail("member2@pollen.org"); @@ -348,14 +364,85 @@ public class FavoriteListServiceTest extends AbstractPollenServiceTest { Assert.fail(); } catch (InvalidFormException e) { // duplicated email - assertErrorKeyFound(e, "email"); + assertErrorKeyFound(e, "email", "weight"); } memberBean1.setEmail("member1@pollen.org"); + try { + service.editFavoriteListMember(savedList1.getEntityId(), memberBean1); + Assert.fail(); + } catch (InvalidFormException e) { + // duplicated email + assertErrorKeyFound(e, "weight"); + } + + memberBean1.setWeight(1); service.editFavoriteListMember(savedList1.getEntityId(), memberBean1); memberBean1.setEmail("member3@pollen.org"); service.editFavoriteListMember(savedList1.getEntityId(), memberBean1); } + + + @Test + public void editChildFavoriteList() throws PollenInvalidSessionTokenException, PollenAuthenticationException, InvalidFormException { + login("jean@pollen.fake", "fake"); + + // create a first list + + FavoriteListBean favoriteListBean1 = new FavoriteListBean(); + favoriteListBean1.setName("list1"); + PollenEntityRef<FavoriteList> savedList1 = service.createFavoriteList(favoriteListBean1); + favoriteListBean1.setId(savedList1); + + FavoriteListBean favoriteListBean2 = new FavoriteListBean(); + favoriteListBean2.setName("list2"); + PollenEntityRef<FavoriteList> savedList2 = service.createFavoriteList(favoriteListBean2); + favoriteListBean2.setId(savedList2); + + ChildFavoriteListBean childList1 = new ChildFavoriteListBean(); + childList1.setChild(favoriteListBean1); + + try { + service.addChildList(favoriteListBean1.getEntityId(), childList1); + Assert.fail(); + } catch (InvalidFormException e) { + // same parent an child, wieght null + assertErrorKeyFound(e, "child", "weight"); + } + + childList1.setWeight(1); + try { + service.addChildList(favoriteListBean1.getEntityId(), childList1); + Assert.fail(); + } catch (InvalidFormException e) { + // same parent an child, + assertErrorKeyFound(e, "child"); + } + + childList1.setChild(favoriteListBean2); + service.addChildList(favoriteListBean1.getEntityId(), childList1); + + ChildFavoriteListBean childList2 = new ChildFavoriteListBean(); + childList2.setChild(favoriteListBean2); + childList2.setWeight(2); + try { + service.addChildList(favoriteListBean1.getEntityId(), childList2); + Assert.fail(); + } catch (InvalidFormException e) { + // duplicated child + assertErrorKeyFound(e, "child"); + } + + childList2.setChild(favoriteListBean1); + try { + service.addChildList(favoriteListBean2.getEntityId(), childList2); + Assert.fail(); + } catch (InvalidFormException e) { + // child is ancestor + assertErrorKeyFound(e, "child"); + } + + } } diff --git a/pollen-ui-riot-js/src/main/web/i18n.json b/pollen-ui-riot-js/src/main/web/i18n.json index 792334b..548834c 100644 --- a/pollen-ui-riot-js/src/main/web/i18n.json +++ b/pollen-ui-riot-js/src/main/web/i18n.json @@ -335,10 +335,14 @@ "favoriteList_member_import": "Importer", "favoriteList_member_importCsv": "Importer des membres à partir d'un fichier", "favoriteList_member_csvFile": "Fichier des membres", - "favoriteList_member_csvFile_exemple": "# Courriel Nom\ndupond@domaine.fr Jean Dupond \npseudo@bleu.fr Arnaud Lemaitre \nmiller@courriel.com Benjamin Miller ", + "favoriteList_member_csvFile_exemple": "# Courriel;Nom;Poids\ndupond@domaine.fr;Jean Dupond;1.00\npseudo@bleu.fr;Arnaud Lemaitre;4.50\nmiller@courriel.com;Benjamin Miller;3.00", "favoriteList_member_csvFile_exemple_label": "Exemple de fichier", + "favoriteList_member_csvFile_exemple_detail": "Si le poids est omis, sa valeur par défaut est 1", "favoriteList_member_importLdap": "Importer des membres à partir d'un annuaire LDAP", "favoriteList_member_ldap": "Adresse de l'annuaire LDAP", + "favoriteList_member_ldap_exemple": "ldap://ldap.domaine.org/ou=companies,o=entreprise?cn,mail?sub?(objectclass=people)\nldaps://login:password@ldap.domaine.org/ou=companies,o=libre-entreprise?cn,mail?sub?(objectclass=people)", + "favoriteList_member_ldap_exemple_label": "Exemple d'adresse LDAP", + "favoriteList_member_ldap_exemple_detail": "Si votre identifiant ou mot de passe contiennent les caractères « : » ou « @ », vous devez les remplacer respectivement par « %3A » et « %40 »", "favoriteList_member_edit": "Modifier ce membre", "favoriteList_member_delete": "Supprimer ce membre", "favoriteList_member_deleteMessage": "Supprimer ce membre ?", @@ -348,6 +352,7 @@ "favoriteList_member_name_placeholder": "Le nom du membre", "favoriteList_member_email": "Courriel", "favoriteList_member_email_placeholder": "Le courriel du membre", + "favoriteList_member_weight": "Poids", "favoriteList_member_ldap_placeholder": "L'adresse de l'annuaire LDAP", "favoriteList_member_add": "Ajouter" }, @@ -678,9 +683,13 @@ "favoriteList_member_importCsv": "Import members from filer", "favoriteList_member_csvFile": "members file", "favoriteList_member_csvFile_exemple": "# Email Name\nsmith@domain.uk John Smith \npseudo@yellow.uk Mathieu Anderson \nmiller@courriel.com William Miller ", - "favoriteList_member_csvFile_exemple_label": "file exemple", + "favoriteList_member_csvFile_exemple_label": "file example", + "favoriteList_member_csvFile_exemple_detail": "If weight is mising, default value is 1", "favoriteList_member_importLdap": "Import members from LDAP repository", "favoriteList_member_ldap": "LDAP repository address", + "favoriteList_member_ldap_exemple": "ldap://ldap.domaine.org/ou=companies,o=entreprise?cn,mail?sub?(objectclass=people)\nldaps://login:password@ldap.domaine.org/ou=companies,o=libre-entreprise?cn,mail?sub?(objectclass=people)", + "favoriteList_member_ldap_exemple_label": "LDAP example", + "favoriteList_member_ldap_exemple_detail": "If your login ou password contains characters \":\" or \"@\", you must remplace by \"%3A\" and \"%40\"", "favoriteList_member_edit": "Edit member", "favoriteList_member_delete": "Delete Member", "favoriteList_member_deleteMessage": "Delete member ?", @@ -690,6 +699,7 @@ "favoriteList_member_name_placeholder": "Member name", "favoriteList_member_email": "Email", "favoriteList_member_email_placeholder": "Member email", + "favoriteList_member_weight": "Weight", "favoriteList_member_ldap_placeholder": "LDAP repository address", "favoriteList_member_add": "Add" } diff --git a/pollen-ui-riot-js/src/main/web/tag/favoriteList/FavoriteList.tag.html b/pollen-ui-riot-js/src/main/web/tag/favoriteList/FavoriteList.tag.html index 39eebb2..d187791 100644 --- a/pollen-ui-riot-js/src/main/web/tag/favoriteList/FavoriteList.tag.html +++ b/pollen-ui-riot-js/src/main/web/tag/favoriteList/FavoriteList.tag.html @@ -95,6 +95,16 @@ require("./MemberCard.tag.html"); placeholder={__.member_email_placeholder} class="c-field {c-field--error : errors.email}"> </div> + <div class="o-form-element"> + <label class="c-label" for="email">{__.member_weight}</label> + <input type="number" + id="weight" + ref="weight" + required + value="1.00" + step="0.01" + class="c-field {c-field--error : errors.email}"> + </div> <div class="actions"> <a class="c-button c-button--ghost-info" href="#/favoriteLists" @@ -119,11 +129,10 @@ require("./MemberCard.tag.html"); ref="csvFile" required class="c-field"> - <div class="file-exemple"> + <div class="exemple"> {__.member_csvFile_exemple_label} - <code class="c-code c-code--multiline"> - {__.member_csvFile_exemple} - </code> + <code class="c-code c-code--multiline">{__.member_csvFile_exemple}</code> + {__.member_csvFile_exemple_detail} </div> </div> <div class="actions"> @@ -151,6 +160,11 @@ require("./MemberCard.tag.html"); required placeholder={__.member_ldap_placeholder} class="c-field"> + <div class="exemple"> + {__.member_ldap_exemple_label} + <code class="c-code c-code--multiline">{__.member_ldap_exemple}</code> + {__.member_ldap_exemple_detail} + </div> </div> <div class="actions"> <a class="c-button c-button--ghost-info" @@ -247,13 +261,15 @@ require("./MemberCard.tag.html"); e.stopPropagation(); let member = { name: this.refs.nameMember.value, - email: this.refs.email.value + email: this.refs.email.value, + weight: this.refs.weight.value }; favoriteListService.addMember(this.favoriteList.id, member).then(() => { this.errors = {}; this.refs.nameMember.value = ""; this.refs.email.value = ""; + this.refs.weight.value = "1.00"; this.refresh(); }, errors => { this.errors = errors; @@ -328,6 +344,20 @@ require("./MemberCard.tag.html"); width: 100%; } + .exemple { + font-size: 0.9em; + padding-left: 25%; + padding-top: 0.5em; + width: 100%; + } + + .exemple code.c-code { + -webkit-user-select: text; /* Chrome all / Safari all */ + -moz-user-select: text; /* Firefox all */ + -ms-user-select: text; /* IE 10+ */ + user-select: text; + } + @media (min-width: 640px) { .o-form-element .c-label:first-child { width: 25%; @@ -343,19 +373,7 @@ require("./MemberCard.tag.html"); display: inline-block; } - .file-exemple { - font-size: 0.9em; - padding-left: 25%; - padding-top: 0.5em; - width: 100%; - } - .file-exemple code.c-code { - -webkit-user-select: text; /* Chrome all / Safari all */ - -moz-user-select: text; /* Firefox all */ - -ms-user-select: text; /* IE 10+ */ - user-select: text; - } } diff --git a/pollen-ui-riot-js/src/main/web/tag/favoriteList/MemberCard.tag.html b/pollen-ui-riot-js/src/main/web/tag/favoriteList/MemberCard.tag.html index bf72e66..edb01f0 100644 --- a/pollen-ui-riot-js/src/main/web/tag/favoriteList/MemberCard.tag.html +++ b/pollen-ui-riot-js/src/main/web/tag/favoriteList/MemberCard.tag.html @@ -6,7 +6,7 @@ <span if={opts.member.name !== opts.member.email}> {opts.member.name} - </span> - {opts.member.email} + {opts.member.email} - {opts.member.weight} </div> <div class="member-actions u-xsmall"> @@ -43,6 +43,16 @@ value={opts.member.email}> <div class="c-hint c-hint--static c-hint--error" each={error in errors.email}>{error}</div> </div> + <div class="o-form-element"> + <label class="c-label" for="email">{__.weight}</label> + <input type="number" + id="weight" + ref="weight" + required + value={opts.member.weight} + step="0.01" + class="c-field {c-field--error : errors.email}"> + </div> <div class="actions"> <button type="button" class="c-button c-button--ghost-info" @@ -88,8 +98,9 @@ e.stopPropagation(); this.opts.member.name = this.refs.name.value; this.opts.member.email = this.refs.email.value; + this.opts.member.weight = this.refs.weight.value; - favoriteListService.saveMemeber(this.opts.favoriteList.id, this.opts.member).then(() => { + favoriteListService.saveMember(this.opts.favoriteList.id, this.opts.member).then(() => { this.errors = {}; this.cancelEdition(); this.update(); -- To stop receiving notification emails like this one, please contact chorem.org SCM administrator <admin+scm@chorem.org>.