Author: fdesbois Date: 2010-05-20 12:42:31 +0200 (Thu, 20 May 2010) New Revision: 3004 Url: http://chorem.org/repositories/revision/pollen/3004 Log: - Refactor from Topia ID in TOPIA_ID - Add error managment for form validation (not tested yet) Added: trunk/pollen-business/src/main/java/org/chorem/pollen/entity/FavoriteParticipantImpl.java trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/data/ErrorReport.java trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/data/FieldValidationException.java Modified: trunk/pollen-business/src/main/java/org/chorem/pollen/EntityQueryProperty.java trunk/pollen-business/src/main/java/org/chorem/pollen/bean/Filter.java trunk/pollen-business/src/main/java/org/chorem/pollen/entity/FavoriteListImpl.java trunk/pollen-business/src/main/java/org/chorem/pollen/entity/PollAccountImpl.java trunk/pollen-business/src/main/java/org/chorem/pollen/service/ServiceFavoriteImpl.java trunk/pollen-business/src/main/xmi/pollen.zargo trunk/pollen-business/src/test/java/org/chorem/pollen/service/ServicePollImplTest.java trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/data/ChoiceField.java trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/models/ParticipantListModel.java trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/models/PollFormModel.java trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/pages/poll/PollForm.java trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/services/PollenManager.java trunk/pollen-ui/src/main/webapp/poll/PollForm.tml Modified: trunk/pollen-business/src/main/java/org/chorem/pollen/EntityQueryProperty.java =================================================================== --- trunk/pollen-business/src/main/java/org/chorem/pollen/EntityQueryProperty.java 2010-05-19 18:25:58 UTC (rev 3003) +++ trunk/pollen-business/src/main/java/org/chorem/pollen/EntityQueryProperty.java 2010-05-20 10:42:31 UTC (rev 3004) @@ -1,66 +1,65 @@ - package org.chorem.pollen; -import org.nuiton.topia.framework.*; +import org.nuiton.topia.framework.TopiaQuery; import org.nuiton.topia.persistence.TopiaEntity; /** * EntityQueryProperty is used to simplify property concatenation in TopiaQuery. - * The usage is simple, the EntityQueryProperty need a mainAlias which represents - * the entity in a TopiaQuery. Then the {@link #nameProperty(String)} - * is called to retrieve the correct property name used for the query. - * Exemple : + * The usage is simple, the EntityQueryProperty need a mainAlias which + * represents the entity in a TopiaQuery. Then the {@link #nameProperty(String)} + * is called to retrieve the correct property name used for the query. Exemple + * : * <pre> * BoatDAO dao = AppDAOHelper.getBoatDAO(topiaContext); - * + * <p/> * // Property used in the query * EntityQueryProperty boatProperty = new EntityQueryProperty("B"); - * + * <p/> * // It's better to create the query with the property name * TopiaQuery query = dao.createQuery(boatProperty.name()); - * + * <p/> * // The property NAME of the boat need to be find equals to "ULUBERLU" * query.add(boatProperty.nameProperty(Boat.NAME), "ULUBERLU"); - * + * <p/> * // It's avoid doing this : * query.add("B." + Boat.NAME, "ULUBERLU"); * </pre> * This last exemple is a simple case but for a more complex query with more * than one entity, it's obvious that concatenation using + is not a good - * practice.<br /> - * You can also use this class as a superclass for each entity, ex : + * practice.<br /> You can also use this class as a superclass for each entity, + * ex : * <pre> * public class BoatProperty extends EntityQueryProperty { - * + * <p/> * public BoatProperty(String mainAlias) { * super(mainAlias); * } - * + * <p/> * public String namePropertyName() { * return nameProperty(Boat.NAME); * } - * } + * } * </pre> - * + * <p/> * Created: 14 avr. 2010 * * @author fdesbois <fdesbois@codelutin.com> */ public class EntityQueryProperty { - /** alias of the entity **/ + /** alias of the entity * */ protected String mainAlias; - /** name of the property used for join in query **/ + /** name of the property used for join in query * */ protected String propertyJoin; - /** class of the entity **/ + /** class of the entity * */ protected Class<? extends TopiaEntity> entityClass; /** * Default constructor. mainAlias, propertyJoin and entityClass are null. - * You can use setters to initalize these three properties. - * You can use {@link #nameProperty(String)} method with a mainAlias null. + * You can use setters to initalize these three properties. You can use + * {@link #nameProperty(String)} method with a mainAlias null. */ public EntityQueryProperty() { } @@ -77,13 +76,13 @@ /** * Constructor with mainAlias and entityClass. * - * @param mainAlias alias of the entity corresponding to this - * EntityQueryProperty + * @param mainAlias alias of the entity corresponding to this + * EntityQueryProperty * @param entityClass class of the entity corresponding to this - * EntityQueryProperty + * EntityQueryProperty */ public EntityQueryProperty(String mainAlias, - Class<? extends TopiaEntity> entityClass) { + Class<? extends TopiaEntity> entityClass) { this(mainAlias); setEntityClass(entityClass); } @@ -111,15 +110,15 @@ * Setter for entityClass. * * @param entityClass class of the entity corresponding to this - * EntityQueryProperty + * EntityQueryProperty */ public void setEntityClass(Class<? extends TopiaEntity> entityClass) { this.entityClass = entityClass; } /** - * Name the entity as a property for a TopiaQuery. Careful, this name can - * be null if no mainAlias is properly set. + * Name the entity as a property for a TopiaQuery. Careful, this name can be + * null if no mainAlias is properly set. * * @return the entity name to use in a TopiaQuery */ @@ -144,7 +143,7 @@ * @return the property name to use in a TopiaQuery */ public String namePropertyId() { - return nameProperty(TopiaEntity.ID); + return nameProperty(TopiaEntity.TOPIA_ID); } /** @@ -153,7 +152,7 @@ * @return the property name to use in a TopiaQuery */ public String namePropertyCreateDate() { - return nameProperty(TopiaEntity.CREATE_DATE); + return nameProperty(TopiaEntity.TOPIA_CREATE_DATE); } /** @@ -170,11 +169,10 @@ } /** - * Get the entityClass associated with this EntityQueryProperty. - * Can be useful in some case, to create other query for exemple or to - * use it in {@link TopiaQuery#addFrom(Class)} method. - * The entityClass need to be set before calling this method to avoid - * NullPointerException. + * Get the entityClass associated with this EntityQueryProperty. Can be + * useful in some case, to create other query for exemple or to use it in + * {@link TopiaQuery#addFrom(Class)} method. The entityClass need to be set + * before calling this method to avoid NullPointerException. * * @return the entity class corresponding to this EntityQueryProperty. */ @@ -191,7 +189,7 @@ * instantiate. * * @return a new TopiaQuery with the main entity as the EntityQueryProperty - * provides it. + * provides it. */ public TopiaQuery newQuery() { return new TopiaQuery(getEntityClass(), name()); Modified: trunk/pollen-business/src/main/java/org/chorem/pollen/bean/Filter.java =================================================================== --- trunk/pollen-business/src/main/java/org/chorem/pollen/bean/Filter.java 2010-05-19 18:25:58 UTC (rev 3003) +++ trunk/pollen-business/src/main/java/org/chorem/pollen/bean/Filter.java 2010-05-20 10:42:31 UTC (rev 3004) @@ -1,13 +1,13 @@ - package org.chorem.pollen.bean; +import org.nuiton.topia.persistence.TopiaEntity; + import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; -import org.nuiton.topia.persistence.TopiaEntity; /** * Filter - * + * <p/> * Created: 23 avr. 2010 * * @author fdesbois @@ -109,11 +109,11 @@ /** * Set the value of referenceId * - * @param entity + * @param entity */ public void setReference(TopiaEntity entity) { String oldReferenceId = this.referenceId; - this.referenceId = entity.getId(); + this.referenceId = entity.getTopiaId(); propertyChangeSupport.firePropertyChange(PROP_REFERENCE_ID, oldReferenceId, referenceId); } Modified: trunk/pollen-business/src/main/java/org/chorem/pollen/entity/FavoriteListImpl.java =================================================================== --- trunk/pollen-business/src/main/java/org/chorem/pollen/entity/FavoriteListImpl.java 2010-05-19 18:25:58 UTC (rev 3003) +++ trunk/pollen-business/src/main/java/org/chorem/pollen/entity/FavoriteListImpl.java 2010-05-20 10:42:31 UTC (rev 3004) @@ -48,4 +48,9 @@ addFavoriteParticipant(favorite); return null; } + + @Override + public String getId() { + return getTopiaId(); + } } Added: trunk/pollen-business/src/main/java/org/chorem/pollen/entity/FavoriteParticipantImpl.java =================================================================== --- trunk/pollen-business/src/main/java/org/chorem/pollen/entity/FavoriteParticipantImpl.java (rev 0) +++ trunk/pollen-business/src/main/java/org/chorem/pollen/entity/FavoriteParticipantImpl.java 2010-05-20 10:42:31 UTC (rev 3004) @@ -0,0 +1,15 @@ +package org.chorem.pollen.entity; + +/** + * Created: 20 mai 2010 + * + * @author fdesbois <fdesbois@codelutin.com> + * @version $Id$ + */ +public class FavoriteParticipantImpl extends FavoriteParticipantAbstract { + + @Override + public String getId() { + return getTopiaId(); + } +} Property changes on: trunk/pollen-business/src/main/java/org/chorem/pollen/entity/FavoriteParticipantImpl.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Modified: trunk/pollen-business/src/main/java/org/chorem/pollen/entity/PollAccountImpl.java =================================================================== --- trunk/pollen-business/src/main/java/org/chorem/pollen/entity/PollAccountImpl.java 2010-05-19 18:25:58 UTC (rev 3003) +++ trunk/pollen-business/src/main/java/org/chorem/pollen/entity/PollAccountImpl.java 2010-05-20 10:42:31 UTC (rev 3004) @@ -61,4 +61,9 @@ addChild(account); return null; } + + @Override + public String getId() { + return getTopiaId(); + } } Modified: trunk/pollen-business/src/main/java/org/chorem/pollen/service/ServiceFavoriteImpl.java =================================================================== --- trunk/pollen-business/src/main/java/org/chorem/pollen/service/ServiceFavoriteImpl.java 2010-05-19 18:25:58 UTC (rev 3003) +++ trunk/pollen-business/src/main/java/org/chorem/pollen/service/ServiceFavoriteImpl.java 2010-05-20 10:42:31 UTC (rev 3004) @@ -1,7 +1,5 @@ package org.chorem.pollen.service; -import java.util.List; -import java.util.Map; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -25,18 +23,23 @@ import org.nuiton.topia.framework.TopiaQuery.Op; import org.nuiton.topia.persistence.TopiaEntity; +import java.util.List; +import java.util.Map; + /** * ServiceFavorite - * + * <p/> * Created: 5 mai 2010 * - * @author fdesbois - * $Id$ + * @author fdesbois $Id: ServiceFavoriteImpl.java 2996 2010-05-14 12:06:15Z + * fdesbois $ */ public class ServiceFavoriteImpl extends ServiceFavoriteAbstract { private Log log = LogFactory.getLog(ServiceUserImpl.class); + private static final String BINDER_CONTEXT_FAVORITE_LIST = "favoriteList"; + private PollenContext context; public void setContext(PollenContext context) { @@ -50,7 +53,7 @@ @Override protected void treateError(TopiaContext transaction, Exception eee, - String message, Object... args) throws PollenException { + String message, Object... args) throws PollenException { context.treateError(transaction, eee, message, args); } @@ -68,7 +71,7 @@ @Override protected void executeCreateFavoriteList(TopiaContext transaction, - FavoriteList list) throws TopiaException, PollenBusinessException { + FavoriteList list) throws TopiaException, PollenBusinessException { FavoriteListDAO dao = PollenDAOHelper.getFavoriteListDAO(transaction); @@ -92,10 +95,10 @@ @Override protected void executeDeleteFavoriteList(TopiaContext transaction, - FavoriteList list) throws TopiaException { + FavoriteList list) throws TopiaException { FavoriteListDAO dao = PollenDAOHelper.getFavoriteListDAO(transaction); - FavoriteList listLoaded = dao.findById(list.getId()); + FavoriteList listLoaded = dao.findByTopiaId(list.getId()); dao.delete(listLoaded); transaction.commitTransaction(); @@ -113,28 +116,28 @@ } /** - * Check if the {@code participant} doesn't already exists with same - * email, name and favoriteList. + * Check if the {@code participant} doesn't already exists with same email, + * name and favoriteList. * - * @param dao used to verify the existing participant + * @param dao used to verify the existing participant * @param participant FavoriteParticipant to check * @throws PollenBusinessException if FavoriteParticipant already exists - * @throws TopiaException for technical errors from ToPIA + * @throws TopiaException for technical errors from ToPIA */ protected void checkFavoriteParticipant(FavoriteParticipantDAO dao, - FavoriteParticipant participant) + FavoriteParticipant participant) throws PollenBusinessException, TopiaException { FavoriteList list = participant.getFavoriteList(); TopiaQuery query = dao.createQuery(). - add(FavoriteParticipant.FAVORITE_LIST, list). - add(FavoriteParticipant.NAME, participant.getName()). - add(FavoriteParticipant.EMAIL, participant.getEmail()); + add(FavoriteParticipant.FAVORITE_LIST, list). + add(FavoriteParticipant.NAME, participant.getName()). + add(FavoriteParticipant.EMAIL, participant.getEmail()); // Check only on entities different from the one in argument if (StringUtils.isNotEmpty(participant.getId())) { - query.add(TopiaEntity.ID, Op.NEQ, participant.getId()); + query.add(TopiaEntity.TOPIA_ID, Op.NEQ, participant.getId()); } // existing participant found @@ -166,7 +169,7 @@ @Override protected void executeCreateFavoriteParticipant(TopiaContext transaction, - FavoriteParticipant participant) + FavoriteParticipant participant) throws PollenBusinessException, TopiaException { FavoriteParticipantDAO dao = @@ -177,8 +180,8 @@ // Create newParticipant with naturalId FavoriteParticipant newParticipant = dao.create(participant.getName(), - participant.getEmail(), - participant.getFavoriteList()); + participant.getEmail(), + participant.getFavoriteList()); // Set other field newParticipant.setWeight(participant.getWeight()); @@ -188,12 +191,12 @@ @Override protected void executeDeleteFavoriteParticipant(TopiaContext transaction, - String id) throws TopiaException { + String id) throws TopiaException { FavoriteParticipantDAO dao = PollenDAOHelper.getFavoriteParticipantDAO(transaction); - FavoriteParticipant participantLoaded = dao.findById(id); + FavoriteParticipant participantLoaded = dao.findByTopiaId(id); dao.delete(participantLoaded); @@ -202,7 +205,7 @@ @Override protected void executeUpdateFavoriteParticipant(TopiaContext transaction, - FavoriteParticipant participant) + FavoriteParticipant participant) throws TopiaException, PollenBusinessException { FavoriteParticipantDAO dao = @@ -211,7 +214,7 @@ checkFavoriteParticipant(dao, participant); FavoriteParticipant participantLoaded = - dao.findById(participant.getId()); + dao.findByTopiaId(participant.getId()); // Set all fields except favoriteList that can't be changed participantLoaded.setName(participant.getName()); @@ -230,7 +233,7 @@ FavoriteParticipantDAO dao = PollenDAOHelper.getFavoriteParticipantDAO(transaction); - FavoriteParticipant result = dao.findById(id); + FavoriteParticipant result = dao.findByTopiaId(id); // Load parent list result.getFavoriteList(); @@ -263,7 +266,7 @@ @Override protected int executeGetNbFavoriteParticipants(TopiaContext transaction, - Filter filter) throws TopiaException { + Filter filter) throws TopiaException { PollenQueryBuilder builder = new PollenQueryBuilder(); Modified: trunk/pollen-business/src/main/xmi/pollen.zargo =================================================================== (Binary files differ) Modified: trunk/pollen-business/src/test/java/org/chorem/pollen/service/ServicePollImplTest.java =================================================================== --- trunk/pollen-business/src/test/java/org/chorem/pollen/service/ServicePollImplTest.java 2010-05-19 18:25:58 UTC (rev 3003) +++ trunk/pollen-business/src/test/java/org/chorem/pollen/service/ServicePollImplTest.java 2010-05-20 10:42:31 UTC (rev 3004) @@ -3,7 +3,6 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.chorem.pollen.PollenDAOHelper; -import org.chorem.pollen.test.AbstractServiceTest; import org.chorem.pollen.common.ChoiceType; import org.chorem.pollen.common.PollType; import org.chorem.pollen.entity.FavoriteList; @@ -15,8 +14,8 @@ import org.chorem.pollen.entity.PollDAO; import org.chorem.pollen.entity.PollImpl; import org.chorem.pollen.entity.UserAccount; +import org.chorem.pollen.test.AbstractServiceTest; import org.junit.Assert; -import org.junit.Before; import org.junit.Test; import org.nuiton.topia.TopiaContext; @@ -45,6 +44,7 @@ private Poll poll; //@Before + public void init() throws Exception { // Initialize service and default user getServicePoll(); @@ -130,7 +130,7 @@ try { PollDAO dao = PollenDAOHelper.getPollDAO(transaction); - Poll pollFound = dao.findById(newPoll.getId()); + Poll pollFound = dao.findByTopiaId(newPoll.getId()); Assert.assertNotNull(pollFound); Assert.assertNotNull(pollFound.getCreator()); Assert.assertEquals(user, pollFound.getCreator().getUserAccount()); @@ -140,7 +140,7 @@ } log.info("test 2 : create poll with new creator"); - poll.getCreator().setUserAccount(null); + poll.getCreator().setUserAccount(null); transaction = beginTransaction(); newPoll = null; @@ -193,7 +193,7 @@ log.info("test 2 : createPollAccounts from two lists : GROUP." + " One of the list is an existing favorite one"); - + transaction = beginTransaction(); try { // Create only list accounts @@ -211,7 +211,7 @@ // Check on list1 if (account.getName().equals(list1.getName())) { Assert.assertEquals(2, account.getChild().size()); - // Check on list2 + // Check on list2 } else if (account.getName().equals(list2.getName())) { Assert.assertEquals(3, account.getChild().size()); // Child are person accounts @@ -252,7 +252,7 @@ PollDAO dao = PollenDAOHelper.getPollDAO(transaction); Assert.assertTrue(dao.existByNaturalId(poll.getUid())); Poll pollFound = dao.findByNaturalId(poll.getUid()); - + // Check pollType and accounts Assert.assertEquals(PollType.FREE, pollFound.getPollType()); Assert.assertEquals(0, pollFound.getPollAccount().size()); Modified: trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/data/ChoiceField.java =================================================================== --- trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/data/ChoiceField.java 2010-05-19 18:25:58 UTC (rev 3003) +++ trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/data/ChoiceField.java 2010-05-20 10:42:31 UTC (rev 3004) @@ -1,7 +1,5 @@ - package org.chorem.pollen.ui.data; -import java.util.Date; import org.apache.commons.fileupload.FileUploadException; import org.apache.commons.lang.StringUtils; import org.apache.tapestry5.upload.services.UploadedFile; @@ -13,28 +11,30 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.Date; + /** - * This class extends ChoiceDTO to have the same properties. It had the - * behavior to be an image or a date depends on the choice type. - * You have to set the type when needed (changing) or using static methods : + * This class extends ChoiceDTO to have the same properties. It had the behavior + * to be an image or a date depends on the choice type. You have to set the type + * when needed (changing) or using static methods : * <pre> * - {@link #getChoiceDate(java.lang.String)} : need the date pattern to format * - {@link #getChoiceImage(java.lang.String)} : need the pollId to save the * image * - {@link #getChoiceText()} * </pre> - * + * <p/> * Before saving choices using servicePoll, you have to save the name using * {@link #saveName()} method : the name to save depends on the choice type. - * + * <p/> * Created: 6 mars 2010 * * @author fdesbois * @version $Revision$ * @since 1.3 - * - * Mise a jour: $Date$ - * par : $Author$ + * <p/> + * Mise a jour: $Date$ par + * : $Author$ */ public class ChoiceField { @@ -74,8 +74,8 @@ this.choice = choice; if (log.isDebugEnabled()) { log.debug("Instanciate ChoiceField : " + - "type = " + getChoiceType() + - " _ name = " + getName()); + "type = " + getChoiceType() + + " _ name = " + getName()); } switch (getChoiceType()) { case DATE: @@ -105,7 +105,7 @@ * Instantiate a new choiceField for an Image ChoiceType. * * @param pollUId used to save the image (corresponding to the folder where - * the image will be saved). + * the image will be saved). * @return the ChoiceField which is image typed * @see #setImageType(java.lang.String) */ @@ -119,7 +119,7 @@ * Instantiate a new choiceField for a Text ChoiceType. * * @return the ChoiceField which is text typed - * @see #setTextType() + * @see #setTextType() */ public static ChoiceField getChoiceText() { ChoiceField result = new ChoiceField(); @@ -128,8 +128,8 @@ } /** - * Change type of the choice to date type. The date type need a - * {@code pattern} to format the date when saving the choice. + * Change type of the choice to date type. The date type need a {@code + * pattern} to format the date when saving the choice. * * @see #saveName() */ @@ -151,9 +151,7 @@ date = null; } - /** - * Change type of the choice to text type. - */ + /** Change type of the choice to text type. */ public void setTextType() { setChoiceType(ChoiceType.TEXT); date = null; @@ -173,7 +171,7 @@ this.image = image; String contentType = StringUtils.lowerCase(image.getContentType()); if (!contentType.contains("image")) { - throw new FileUploadException("wrong type " + + throw new FileUploadException("wrong type " + image.getContentType() + " for image upload " + image.getFileName()); } @@ -215,9 +213,10 @@ * correspond to the image file name ; * - TEXT : the text becomes the choice name. * </pre> + * * @param serviceImage used to save the image */ - public void saveName(ServiceImage serviceImage) { + public void saveName(ServiceImage serviceImage) { String name = ""; switch (getChoiceType()) { case DATE: @@ -232,7 +231,7 @@ setName(name); } - protected Choice getChoice() { + public Choice getChoice() { if (choice == null) { choice = new ChoiceImpl(); } Added: trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/data/ErrorReport.java =================================================================== --- trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/data/ErrorReport.java (rev 0) +++ trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/data/ErrorReport.java 2010-05-20 10:42:31 UTC (rev 3004) @@ -0,0 +1,57 @@ +package org.chorem.pollen.ui.data; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +/** + * Created: 20 mai 2010 + * + * @author fdesbois <fdesbois@codelutin.com> + * @version $Id$ + */ +public class ErrorReport { + + protected Map<String, String> fieldErrors; + + protected Collection<String> errors; + + public void recordFieldError(String field, String message) { + getFieldErrors().put(field, message); + } + + public void recordError(String message) { + getErrors().add(message); + } + + public Map<String, String> getFieldErrors() { + if (fieldErrors == null) { + fieldErrors = new HashMap<String, String>(); + } + return fieldErrors; + } + + public Collection<String> getErrors() { + if (errors == null) { + errors = new ArrayList<String>(); + } + return errors; + } + + public Collection<String> getAllErrors() { + Collection<String> allErrors = new ArrayList<String>(getErrors()); + allErrors.addAll(getFieldErrors().values()); + return allErrors; + } + + public void clear() { + errors = null; + fieldErrors = null; + } + + public boolean hasErrors() { + return !getAllErrors().isEmpty(); + } + +} Property changes on: trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/data/ErrorReport.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/data/FieldValidationException.java =================================================================== --- trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/data/FieldValidationException.java (rev 0) +++ trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/data/FieldValidationException.java 2010-05-20 10:42:31 UTC (rev 3004) @@ -0,0 +1,27 @@ +package org.chorem.pollen.ui.data; + +import org.apache.tapestry5.ValidationException; + +/** + * Created: 20 mai 2010 + * + * @author fdesbois <fdesbois@codelutin.com> + * @version $Id$ + */ +public class FieldValidationException extends ValidationException { + + protected String field; + + public FieldValidationException(String message) { + super(message); + } + + public FieldValidationException(String field, String message) { + super(message); + this.field = field; + } + + public String getField() { + return field; + } +} Property changes on: trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/data/FieldValidationException.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Modified: trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/models/ParticipantListModel.java =================================================================== --- trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/models/ParticipantListModel.java 2010-05-19 18:25:58 UTC (rev 3003) +++ trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/models/ParticipantListModel.java 2010-05-20 10:42:31 UTC (rev 3004) @@ -31,10 +31,10 @@ public static final String PROPERTY_PARTICIPANTS = "participants"; - protected ServicePoll service; +// protected ServicePoll service; +// +// protected PollenManager manager; - protected PollenManager manager; - protected ParticipantList list; protected ParticipantMap participants; @@ -49,14 +49,23 @@ } }; - public ParticipantListModel(ServicePoll service, PollenManager manager) { - this.service = service; - this.manager = manager; + public ParticipantListModel() { +// this.service = service; +// this.manager = manager; participants = new ParticipantMap(); } - public Participant addNewParticipant() { - Participant newParticipant = service.getNewPollParticipant(); + /** + * Instantiate a new participant and add it to the current participants + * list. + * + * @param servicePoll Service used to instantiate a new participant + * @param manager Service to manage temporary id if needed + * @return a new Participant + */ + public Participant addNewParticipant(ServicePoll servicePoll, + PollenManager manager) { + Participant newParticipant = servicePoll.getNewPollParticipant(); String id = manager.createPollenId(); participants.put(id, newParticipant); ((TopiaEntity) newParticipant).addPropertyListener(participantsListener); @@ -77,7 +86,14 @@ return participants.values(); } - public void setList(ParticipantList participantList) { + /** + * Set a {@code participantList} for current usage. Will initialize + * participants from the list. + * + * @param manager Service used to manage temporary id if needed + * @param participantList ParticipantList to set as current one + */ + public void setList(PollenManager manager, ParticipantList participantList) { if (logger.isDebugEnabled()) { logger.debug("Set current list : " + participantList.getName()); } Modified: trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/models/PollFormModel.java =================================================================== --- trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/models/PollFormModel.java 2010-05-19 18:25:58 UTC (rev 3003) +++ trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/models/PollFormModel.java 2010-05-20 10:42:31 UTC (rev 3004) @@ -2,21 +2,29 @@ import org.apache.commons.lang.StringUtils; import org.apache.tapestry5.ValueEncoder; +import org.apache.tapestry5.ioc.Messages; import org.chorem.pollen.PollenBusinessException; import org.chorem.pollen.common.PollType; +import org.chorem.pollen.entity.Choice; import org.chorem.pollen.entity.ParticipantList; import org.chorem.pollen.entity.Poll; import org.chorem.pollen.entity.UserAccount; import org.chorem.pollen.service.ServicePoll; +import org.chorem.pollen.ui.data.ChoiceField; +import org.chorem.pollen.ui.data.FieldValidationException; import org.chorem.pollen.ui.pages.poll.PollForm; import org.chorem.pollen.ui.services.PollenManager; +import org.chorem.pollen.ui.services.ServiceImage; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; +import java.util.ArrayList; import java.util.Collection; +import java.util.Date; import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; /** @@ -43,7 +51,7 @@ public static final String PROPERTY_LISTS = "lists"; /** Service to manage poll */ - protected ServicePoll service; +// protected ServicePoll service; /** Current poll in edition */ protected Poll poll; @@ -51,6 +59,8 @@ /** Current lists in edition */ protected Map<String, ParticipantList> lists; + protected List<ChoiceField> choices; + /** Current listModel that contains current edited list and its participants */ protected ParticipantListModel listModel; @@ -67,18 +77,13 @@ }; /** - * Constructor of PollFormModel. Need services {@code servicePoll} and - * {@code manager} to manage the current edited poll. Use {@link - * #initPoll(String, UserAccount)} to initialize the poll. - * - * @param servicePoll ServicePoll to manage poll - * @param manager PollenManager to manage ids + * Constructor of PollFormModel. Use {@link #initPoll(ServicePoll, String, + * UserAccount)} to initialize the poll. */ - public PollFormModel(ServicePoll servicePoll, - PollenManager manager) { - this.service = servicePoll; + public PollFormModel() { +// this.service = servicePoll; lists = new LinkedHashMap<String, ParticipantList>(); - listModel = new ParticipantListModel(service, manager); + listModel = new ParticipantListModel(); listModel.addPropertyChangeListener(listsListener); } @@ -91,26 +96,26 @@ * @param user Connected user as creator of a new poll (can be null if no * user is connected). */ - public void initPoll(String uid, UserAccount user) { + public void initPoll(ServicePoll servicePoll, String uid, UserAccount user) { if (StringUtils.isNotEmpty(uid)) { if (logger.isDebugEnabled()) { logger.debug("Get existing poll with pollUID = " + uid); } - poll = service.getPollForUpdate(uid); + poll = servicePoll.getPollForUpdate(uid); // TODO : init advancedOptions // TODO-fdesbois-2010-05-19 : exception need to be throw if uid not correspond to an existing poll } else { if (logger.isDebugEnabled()) { logger.debug("Init new poll"); } - poll = service.getNewPoll(user); + poll = servicePoll.getNewPoll(user); createMode = true; } } /** * Get the current poll. Will be null if initializion with {@link - * #initPoll(String, UserAccount)} has not been called. + * #initPoll(ServicePoll, String, UserAccount)} has not been called. * * @return the current poll. */ @@ -127,20 +132,43 @@ return createMode; } + public List<ChoiceField> getChoices() { + if (choices == null) { + choices = new ArrayList<ChoiceField>(); + if (createMode) { + // Initialized to choice TEXT type + for (int i = 0; i < 4; i++) { + choices.add(ChoiceField.getChoiceText()); + } + } else { + for (Choice current : poll.getChoice()) { + choices.add(new ChoiceField(poll, current)); + } + } + } + return choices; + } + /** * Change the poll type to {@code type}. The lists managment will depends on * poll type. For a {@link PollType#RESTRICTED} poll, a new list will be * automatically added and set for current usage. For a {@link * PollType#GROUP} poll, the listModel is simply reset. * - * @param type PollType to change + * @param servicePoll Service used to add a new list for restricted poll + * @param manager Service to manage temporary id on participants of the + * unique restricted list + * @param type PollType to change + * @see #addNewList(ServicePoll, String) + * @see ParticipantListModel#setList(PollenManager, ParticipantList) */ - public void setPollType(PollType type) { + public void setPollType(ServicePoll servicePoll, PollenManager manager, + PollType type) { lists.clear(); if (type.isRestricted()) { - addNewList(DEFAULT_LIST_NAME); + addNewList(servicePoll, DEFAULT_LIST_NAME); // Set automatically the current list to the unique one - listModel.setList(lists.get(DEFAULT_LIST_NAME)); + listModel.setList(manager, lists.get(DEFAULT_LIST_NAME)); } else if (type.isGroup()) { listModel.reset(); } @@ -166,14 +194,15 @@ * be added if the {@code listName} is empty or if a list with this {@code * listName} already exists. * - * @param listName for the new list to add + * @param servicePoll Service used to instantiate a new ParticipantList + * @param listName for the new list to add * @return true if the list has been added, false otherwise * @see #addList(ParticipantList) */ - public boolean addNewList(String listName) { + public boolean addNewList(ServicePoll servicePoll, String listName) { boolean result = false; if (StringUtils.isNotEmpty(listName)) { - ParticipantList newList = service.getNewPollList(); + ParticipantList newList = servicePoll.getNewPollList(); newList.setName(listName); return addList(newList); } @@ -220,11 +249,14 @@ * list will be automatically saved. If error occurs during save, the * previous list will be refresh (no list change will be done). * + * @param manager Service used to manage temporary id on participants from + * the list to set * @param listName name of the list to set (empty name will be ignored) * @throws PollenBusinessException for saving error (doubloons) * @see #saveCurrentList() */ - public void setCurrentList(String listName) throws PollenBusinessException { + public void setCurrentList(PollenManager manager, String listName) + throws PollenBusinessException { if (StringUtils.isNotEmpty(listName)) { ParticipantList list = getCurrentList(); try { @@ -237,7 +269,7 @@ } finally { // Previous list will be keeped if error occurs during save. // Apply change in listModel - listModel.setList(list); + listModel.setList(manager, list); } } } @@ -272,10 +304,75 @@ listModel.persistParticipants(); } - public void create() throws PollenBusinessException { - service.createPoll(poll, getLists()); + /** + * Create the poll in business. This will generate choice name to be persist + * and used the current lists for restriction. + * + * @param servicePoll Service used to create the poll. + * @param serviceImage Service used to manage image choices save. + * @throws PollenBusinessException + */ + public void create(ServicePoll servicePoll, ServiceImage serviceImage) + throws PollenBusinessException { + poll.clearChoice(); + for (ChoiceField choiceField : getChoices()) { + choiceField.saveName(serviceImage); + poll.addChoice(choiceField.getChoice()); + } + servicePoll.createPoll(poll, getLists()); } + public void validate(Messages messages) throws FieldValidationException { + + // Initialize beginDate if needed + Date beginDate = poll.getBeginDate(); + if (beginDate == null) { + beginDate = new Date(); + poll.setBeginDate(beginDate); + } + + // Check endDate + Date endDate = poll.getEndDate(); + if (endDate != null && endDate.before(beginDate)) { + throw new FieldValidationException( + PollForm.FORM_FIELD_END_DATE, + "error endDate before beginDate"); + } + + // Add choices is allowed after creation + if (poll.getChoiceAddAllowed()) { + + // Initialize beginChoiceDate if needed + Date beginChoiceDate = poll.getBeginChoiceDate(); + if (beginChoiceDate == null) { + beginChoiceDate = new Date(); + poll.setBeginChoiceDate(beginChoiceDate); + } + + // Check beginChoiceDate + if (endDate != null && beginChoiceDate.after(endDate)) { + throw new FieldValidationException( + PollForm.FORM_FIELD_BEGIN_CHOICE_DATE, + "error beginChoiceDate after endDate"); + } + + // Check endChoiceDate + Date endChoiceDate = poll.getEndChoiceDate(); + if (endChoiceDate != null && endChoiceDate.before(beginChoiceDate)) { + throw new FieldValidationException( + PollForm.FORM_FIELD_END_CHOICE_DATE, + "error endChoiceDate before beginChoiceDate"); + } + } + } + + public Date getBeginDate() { + if (poll.getBeginDate() == null) { + poll.setBeginDate(new Date()); + } + return poll.getBeginDate(); + } + /** * ValueEncoder toClient is used to convert {@code value} to the list name. * Modified: trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/pages/poll/PollForm.java =================================================================== --- trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/pages/poll/PollForm.java 2010-05-19 18:25:58 UTC (rev 3003) +++ trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/pages/poll/PollForm.java 2010-05-20 10:42:31 UTC (rev 3004) @@ -17,11 +17,11 @@ import org.apache.tapestry5.ioc.Messages; import org.apache.tapestry5.ioc.annotations.Inject; import org.apache.tapestry5.json.JSONObject; +import org.apache.tapestry5.services.ComponentSource; import org.chorem.pollen.PollenBusinessException; import org.chorem.pollen.common.ChoiceType; import org.chorem.pollen.common.PollType; import org.chorem.pollen.common.VoteCountingType; -import org.chorem.pollen.entity.Choice; import org.chorem.pollen.entity.Participant; import org.chorem.pollen.entity.ParticipantList; import org.chorem.pollen.entity.Poll; @@ -33,15 +33,16 @@ import org.chorem.pollen.ui.components.Border; import org.chorem.pollen.ui.data.AddressBar; import org.chorem.pollen.ui.data.ChoiceField; +import org.chorem.pollen.ui.data.FieldValidationException; import org.chorem.pollen.ui.models.ParticipantListModel; import org.chorem.pollen.ui.models.PollFormModel; import org.chorem.pollen.ui.services.PollenManager; +import org.chorem.pollen.ui.services.ServiceImage; import org.nuiton.web.tapestry5.components.FeedBack; import org.slf4j.Logger; import java.text.DateFormat; import java.text.SimpleDateFormat; -import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.List; @@ -150,8 +151,8 @@ if (log.isDebugEnabled()) { log.debug("-------- NEW POLL FORM MODEL --------"); } - model = new PollFormModel(servicePoll, manager); - model.initPoll(pollUID, getUserConnected()); + model = new PollFormModel(); + model.initPoll(servicePoll, pollUID, getUserConnected()); } return model; } @@ -342,7 +343,7 @@ return getPoll().getPollType().isFree(); } - /** ******************* LISTS **************************************** */ + /** ****************** LISTS **************************************** */ @Inject private ComponentResources resources; @@ -416,7 +417,7 @@ @Log Object onUpdatePollType(String value) { - getModel().setPollType(PollType.valueOf(value)); + getModel().setPollType(servicePoll, manager, PollType.valueOf(value)); return refreshListZone(); } @@ -439,9 +440,9 @@ @Log void onSelectedFromAddList() { // Set flag for editing lists - setEditListsFlag(); + edited = true; // Add new list in model - getModel().addNewList(listName); + getModel().addNewList(servicePoll, listName); // Set the new list as selected one setSelectedList(listName); // Reset form field before refresh form @@ -451,7 +452,7 @@ @Log void onSelectedFromEditList(String listName) { // Set flag for editing lists - setEditListsFlag(); + edited = true; // Set the selected list setSelectedList(listName); } @@ -460,7 +461,7 @@ // Change current list, will save the previous current one // Errors can appear during saving previous participants. try { - getModel().setCurrentList(listName); + getModel().setCurrentList(manager, listName); } catch (PollenBusinessException eee) { String message = manager.getErrorMessage(eee, messages, logger); listsFeedback.addError(message); @@ -476,7 +477,7 @@ /** PARTICIPANTS FOR LIST ** */ Object onAddRowFromParticipants() { - return getListModel().addNewParticipant(); + return getListModel().addNewParticipant(servicePoll, manager); } void onRemoveRowFromParticipants(Participant participant) { @@ -488,12 +489,8 @@ return listsZone.getBody(); } - protected void setEditListsFlag() { - editLists = true; - } + /** ********************** CHOIX **************************************** */ - /** *********************** CHOIX **************************************** */ - @Property private ChoiceField choice; @@ -518,20 +515,21 @@ * @return a list of ChoiceDTO */ public List<ChoiceField> getChoices() throws PollenBusinessException { - if (choices == null) { - choices = new ArrayList<ChoiceField>(); - if (isCreateMode()) { - // Initialized to choice TEXT type - for (int i = 0; i < 4; i++) { - choices.add(ChoiceField.getChoiceText()); - } - } else { - for (Choice current : getPoll().getChoice()) { - choices.add(new ChoiceField(getPoll(), current)); - } - } - } - return choices; +// if (choices == null) { +// choices = new ArrayList<ChoiceField>(); +// if (isCreateMode()) { +// // Initialized to choice TEXT type +// for (int i = 0; i < 4; i++) { +// choices.add(ChoiceField.getChoiceText()); +// } +// } else { +// for (Choice current : getPoll().getChoice()) { +// choices.add(new ChoiceField(getPoll(), current)); +// } +// } +// } +// return choices; + return getModel().getChoices(); } public Block getChoiceTypeBlock() { @@ -552,12 +550,17 @@ private PollStep step; + private boolean edited; + @Property private boolean refreshChoicesZone; @InjectComponent private Zone choicesZone; + @Inject + private ServiceImage serviceImage; + @Log Object onChangeFromChoiceType(String value) { ChoiceType type = ChoiceType.valueOf(value); @@ -575,11 +578,13 @@ @Log void onSelectedFromChoiceStep() { step = PollStep.CHOICES; + edited = true; } @Log void onSelectedFromMainStep() { step = PollStep.MAIN; + edited = true; } public boolean isChoiceStep() { @@ -590,11 +595,35 @@ return step.equals(PollStep.MAIN); } + @Inject + private ComponentSource componentSource; + + public static final String FORM_FIELD_BEGIN_DATE = "beginDate"; + + public static final String FORM_FIELD_END_DATE = "endDate"; + + public static final String FORM_FIELD_BEGIN_CHOICE_DATE = "beginChoiceDate"; + + public static final String FORM_FIELD_END_CHOICE_DATE = "endChoiceDate"; + @Log + void onValidateForm() { + if (!edited) { + // Need validations on dates + try { + getModel().validate(messages); + getModel().create(servicePoll, serviceImage); + } catch (FieldValidationException eee) { + manager.recordFormError(eee, mainForm, componentSource); + } catch (PollenBusinessException eee) { + String message = manager.getErrorMessage(eee, messages, logger); + mainForm.recordError(message); + } + } + } + + @Log Object onSuccess() { -// if (!editLists) { -// saveCurrentList(); -// } return mainZone; } Modified: trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/services/PollenManager.java =================================================================== --- trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/services/PollenManager.java 2010-05-19 18:25:58 UTC (rev 3003) +++ trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/services/PollenManager.java 2010-05-20 10:42:31 UTC (rev 3004) @@ -21,14 +21,20 @@ package org.chorem.pollen.ui.services; +import org.apache.tapestry5.Field; +import org.apache.tapestry5.corelib.components.Form; import org.apache.tapestry5.ioc.Messages; import org.apache.tapestry5.ioc.services.RegistryShutdownListener; import org.apache.tapestry5.ioc.services.SymbolProvider; import org.apache.tapestry5.ioc.util.CaseInsensitiveMap; +import org.apache.tapestry5.runtime.Component; +import org.apache.tapestry5.services.ComponentSource; import org.chorem.pollen.PollenBusinessException; import org.chorem.pollen.PollenContext; import org.chorem.pollen.PollenProperty; import org.chorem.pollen.service.ServiceUser; +import org.chorem.pollen.ui.data.ErrorReport; +import org.chorem.pollen.ui.data.FieldValidationException; import org.nuiton.util.ApplicationConfig; import org.slf4j.Logger; @@ -123,19 +129,53 @@ return context.createPollenUrlId(); } - public String getErrorMessage(PollenBusinessException eee, + public String getErrorMessage(PollenBusinessException error, Messages messages, Logger logger) { if (logger.isDebugEnabled()) { - logger.debug("ERROR from business : " + eee.getMessage() + - " _ args = " + Arrays.toString(eee.getArgs())); + logger.debug("ERROR from business : " + error.getMessage() + + " _ args = " + Arrays.toString(error.getArgs())); } String message = null; - if (eee.getArgs() != null) { - message = messages.format(eee.getMessage(), eee.getArgs()); + if (error.getArgs() != null) { + message = messages.format(error.getMessage(), error.getArgs()); } else { - message = messages.get(eee.getMessage()); + message = messages.get(error.getMessage()); } return message; } + public void recordFormError(FieldValidationException error, + Form form, ComponentSource componentSource) + throws ClassCastException { + if (error.getField() == null) { + form.recordError(error.getMessage()); + } else { + Field field = getFieldByName(error.getField(), componentSource); + form.recordError(field, error.getMessage()); + } + } + + public void recordFormErrors(ErrorReport report, + Form form, ComponentSource componentSource) + throws ClassCastException { + + for (Map.Entry<String, String> entry : report.getFieldErrors().entrySet()) { + Field field = getFieldByName(entry.getKey(), componentSource); + form.recordError(field, entry.getValue()); + } + for (String message : report.getErrors()) { + form.recordError(message); + } + } + + protected Field getFieldByName(String field, ComponentSource componentSource) + throws ClassCastException { + Component component = componentSource.getComponent(field); + if (!(component instanceof Field)) { + throw new ClassCastException("invalid cast to Field from : " + + component.getClass().getName()); + } + return (Field) component; + } + } Modified: trunk/pollen-ui/src/main/webapp/poll/PollForm.tml =================================================================== --- trunk/pollen-ui/src/main/webapp/poll/PollForm.tml 2010-05-19 18:25:58 UTC (rev 3003) +++ trunk/pollen-ui/src/main/webapp/poll/PollForm.tml 2010-05-20 10:42:31 UTC (rev 3004) @@ -5,50 +5,57 @@ xmlns:t="http://tapestry.apache.org/schema/tapestry_5_1_0.xsd" xmlns:p="tapestry:parameter"> -<h1 class="titlePoll"> + <h1 class="titlePoll"> <t:if t:test="createMode"> - ${message:mainTitle-create} - <p:else>${poll.title}</p:else> + ${message:mainTitle-create} + <p:else>${poll.title}</p:else> </t:if> -</h1> + </h1> -<t:zone t:id="mainZone" t:update="show"> -<form t:type="form" t:id="mainForm" t:zone="mainZone" action="post"> -<t:errors /> -<t:formFragment t:id="mainFormFragment" t:visible="mainStep"> + <t:zone t:id="mainZone" t:update="show"> + <form t:type="form" t:id="mainForm" t:zone="mainZone" action="post"> + <t:errors /> + <t:formFragment t:id="mainFormFragment" t:visible="mainStep"> -<!-- MAIN INFOS --> -<div id="p-pollForm-mainInfos"> - <fieldset> - <legend> - <img class="form-toggle" src="${asset:context:img/1uparrow.png}" /> ${message:legend-mainInfos} - </legend> - <div class="form-block"> - <p> - <span><label t:type="label" t:for="title" />:</span> + <!-- MAIN INFOS --> + <div id="p-pollForm-mainInfos"> + <fieldset> + <legend> + <img class="form-toggle" + src="${asset:context:img/1uparrow.png}" alt="toggle" /> ${message:legend-mainInfos} + </legend> + <div class="form-block"> + <p> + <span><label t:type="label" t:for="title" />: + </span> <input type="text" t:type="textfield" class="title" t:id="title" value="poll.title" t:validate="required" /> - </p> + </p> - <p> - <span><label t:type="label" t:for="creatorName" />:</span> + <p> + <span><label t:type="label" t:for="creatorName" />: + </span> <input type="text" t:type="textfield" t:id="creatorName" value="poll.creator.name" t:validate="required,minlength=2" /> <label t:type="label" t:for="email" />: <input type="text" t:type="textfield" class="email" t:id="email" value="poll.creator.email" t:validate="regexp" /> - </p> + </p> - <p> - <span><label t:type="label" t:for="description" />: </span> + <p> + <span><label t:type="label" t:for="description" />: + </span> <textarea t:type="textarea" cols="80" rows="2" - t:id="description" t:value="poll.description">${poll.description}</textarea> - </p> + t:id="description" t:value="poll.description"> + ${poll.description} + </textarea> + </p> - <p> + <p> <!-- FIXME : validate by regexp doesn't work : seems to be caused by dateTimeField component --> - <span><label t:type="label" t:for="beginDate" />: </span> + <span><label t:type="label" t:for="beginDate" />: + </span> <input t:type="ck/dateTimeField" t:id="beginDate" value="poll.beginDate" t:validate="regexp" t:datePattern="message:date-pattern" t:timePicker="true" @@ -62,370 +69,371 @@ <label t:type="label" t:for="voteCountingType" />: <select t:type="select" t:id="voteCountingType" t:value="poll.voteCountingType" t:validate="required"> - <option></option> + <option></option> </select> - <span t:type="ck/Tooltip" title="${message:help}" - t:value="${message:voteCounting-help}" - t:effect="appear"> - <img src="${asset:context:img/help.png}" - alt="${message:help}" /> - </span> - </p> + <span t:type="ck/Tooltip" title="${message:help}" + t:value="${message:voteCounting-help}" + t:effect="appear"> + <img src="${asset:context:img/help.png}" + alt="${message:help}" /> + </span> + </p> + </div> + </fieldset> </div> - </fieldset> -</div> -<!-- OPTIONS --> -<div id="p-pollForm-options"> - <fieldset> - <legend> - <!--<input t:type="checkbox" t:id="advancedOptions" t:mixins="triggerfragment" t:fragment="optionsFragment"/>--> - <!--<label t:type="label" t:for="advancedOptions"/>--> - <img class="form-toggle" - src="${asset:context:img/1downarrow.png}" /> ${message:legend-options} - </legend> - <div class="form-block clearfix" style="display:none;"> - <!--<t:formFragment t:id="optionsFragment" visible="advancedOptions">--> - <!-- LEFT COLUMN --> - <div class="left-column fleft"> + <!-- OPTIONS --> + <div id="p-pollForm-options"> + <fieldset> + <legend> + <!--<input t:type="checkbox" t:id="advancedOptions" t:mixins="triggerfragment" t:fragment="optionsFragment"/>--> + <!--<label t:type="label" t:for="advancedOptions"/>--> + <img class="form-toggle" + src="${asset:context:img/1downarrow.png}" /> ${message:legend-options} + </legend> + <div class="form-block clearfix" style="display:none;"> + <!--<t:formFragment t:id="optionsFragment" visible="advancedOptions">--> + <!-- LEFT COLUMN --> + <div class="left-column fleft"> <p> - <input t:type="checkbox" t:id="anonymous" - value="poll.anonymous" /> - <label t:type="label" t:for="anonymous" /> - <span t:type="ck/Tooltip" title="message:help" - t:value="message:anonymous-help" - t:effect="appear"> - <img src="${asset:context:img/help.png}" - alt="message:help" /> - </span> + <input t:type="checkbox" t:id="anonymous" + value="poll.anonymous" /> + <label t:type="label" t:for="anonymous" /> + <span t:type="ck/Tooltip" title="message:help" + t:value="message:anonymous-help" + t:effect="appear"> + <img src="${asset:context:img/help.png}" + alt="message:help" /> + </span> </p> <p> - <input t:type="checkbox" t:id="continuousResults" - value="poll.continuousResults" /> - <label t:type="label" t:for="continuousResults" /> - <span t:type="ck/Tooltip" title="message:help" - t:value="message:continuousResults-help" - t:effect="appear"> - <img src="${asset:context:img/help.png}" - alt="message:help" /> - </span> + <input t:type="checkbox" t:id="continuousResults" + value="poll.continuousResults" /> + <label t:type="label" t:for="continuousResults" /> + <span t:type="ck/Tooltip" title="message:help" + t:value="message:continuousResults-help" + t:effect="appear"> + <img src="${asset:context:img/help.png}" + alt="message:help" /> + </span> </p> <p> - <input t:type="checkbox" t:id="choiceAddAllowed" - value="poll.choiceAddAllowed" - t:mixins="triggerfragment" - t:fragment="choiceDateFragment" /> - <label t:type="label" t:for="choiceAddAllowed" /> - <span t:type="ck/Tooltip" title="message:help" - t:value="message:choiceAddAllowed-help}" - t:effect="appear"> - <img src="${asset:context:img/help.png}" - alt="message:help" /> - </span> + <input t:type="checkbox" t:id="choiceAddAllowed" + value="poll.choiceAddAllowed" + t:mixins="triggerfragment" + t:fragment="choiceDateFragment" /> + <label t:type="label" t:for="choiceAddAllowed" /> + <span t:type="ck/Tooltip" title="message:help" + t:value="message:choiceAddAllowed-help}" + t:effect="appear"> + <img src="${asset:context:img/help.png}" + alt="message:help" /> + </span> </p> <p> - <t:formFragment t:id="choiceDateFragment" - t:visible="poll.choiceAddAllowed"> - <label t:type="label" t:for="beginChoiceDate" /> - <input t:type="ck/dateTimeField" t:id="beginChoiceDate" - value="poll.beginChoiceDate" t:validate="regexp" - t:datePattern="message:date-pattern" - t:timePicker="true" - t:timePickerAdjacent="true" /> - <br /> - <label t:type="label" t:for="endChoiceDate" /> - <input t:type="ck/dateTimeField" t:id="endChoiceDate" - value="poll.endChoiceDate" t:validate="regexp" - t:datePattern="message:date-pattern" - t:timePicker="true" - t:timePickerAdjacent="true" /> - </t:formFragment> + <t:formFragment t:id="choiceDateFragment" + t:visible="poll.choiceAddAllowed"> + <label t:type="label" t:for="beginChoiceDate" /> + <input t:type="ck/dateTimeField" t:id="beginChoiceDate" + value="poll.beginChoiceDate" t:validate="regexp" + t:datePattern="message:date-pattern" + t:timePicker="true" + t:timePickerAdjacent="true" /> + <br /> + <label t:type="label" t:for="endChoiceDate" /> + <input t:type="ck/dateTimeField" t:id="endChoiceDate" + value="poll.endChoiceDate" t:validate="regexp" + t:datePattern="message:date-pattern" + t:timePicker="true" + t:timePickerAdjacent="true" /> + </t:formFragment> </p> <p> - <input t:type="checkbox" t:id="sendNotification" - value="hasNotification" - disabled="notificationDisabled" - t:mixins="triggerfragment" - t:fragment="notificationFragment" /> - <label t:type="label" t:for="sendNotification" /> - <span t:type="ck/Tooltip" title="message:help" - t:value="message:sendNotification-help" - t:effect="appear"> - <img src="${asset:context:img/help.png}" - alt="message:help" /> - </span> + <input t:type="checkbox" t:id="sendNotification" + value="hasNotification" + disabled="notificationDisabled" + t:mixins="triggerfragment" + t:fragment="notificationFragment" /> + <label t:type="label" t:for="sendNotification" /> + <span t:type="ck/Tooltip" title="message:help" + t:value="message:sendNotification-help" + t:effect="appear"> + <img src="${asset:context:img/help.png}" + alt="message:help" /> + </span> </p> <p> - <t:formFragment id="notificationHidden" - t:id="notificationFragment" - t:visible="hasNotification"> - <label t:type="label" t:for="notification" /> - <input t:type="textfield" t:id="notification" - value="notification.sensibility" t:size="3" - t:validate="min=0" /> - ${message:notification-label2} - </t:formFragment> + <t:formFragment id="notificationHidden" + t:id="notificationFragment" + t:visible="hasNotification"> + <label t:type="label" t:for="notification" /> + <input t:type="textfield" t:id="notification" + value="notification.sensibility" t:size="3" + t:validate="min=0" /> + ${message:notification-label2} + </t:formFragment> </p> - </div> - <!-- RIGHT COLUMN --> - <div class="fleft"> + </div> + <!-- RIGHT COLUMN --> + <div class="fleft"> <p> - <input t:type="checkbox" t:id="anonymousVoteAllowed" - value="poll.anonymousVoteAllowed" - disabled="anonymousVoteAllowedDisabled" /> - <label t:type="label" t:for="anonymousVoteAllowed" /> - <span t:type="ck/Tooltip" title="message:help" - t:value="message:anonymousVoteAllowed-help" - t:effect="appear"> - <img src="${asset:context:img/help.png}" - alt="message:help" /> - </span> + <input t:type="checkbox" t:id="anonymousVoteAllowed" + value="poll.anonymousVoteAllowed" + disabled="anonymousVoteAllowedDisabled" /> + <label t:type="label" t:for="anonymousVoteAllowed" /> + <span t:type="ck/Tooltip" title="message:help" + t:value="message:anonymousVoteAllowed-help" + t:effect="appear"> + <img src="${asset:context:img/help.png}" + alt="message:help" /> + </span> </p> <p> - <input t:type="checkbox" t:id="publicResults" - value="poll.publicResults" - disabled="publicResultsDisabled" /> - <label t:type="label" t:for="publicResults" /> - <span t:type="ck/Tooltip" title="message:help" - t:value="message:publicResults-help" - t:effect="appear"> - <img src="${asset:context:img/help.png}" - alt="message:help" /> - </span> + <input t:type="checkbox" t:id="publicResults" + value="poll.publicResults" + disabled="publicResultsDisabled" /> + <label t:type="label" t:for="publicResults" /> + <span t:type="ck/Tooltip" title="message:help" + t:value="message:publicResults-help" + t:effect="appear"> + <img src="${asset:context:img/help.png}" + alt="message:help" /> + </span> </p> <p> - <input t:type="checkbox" t:id="choiceNb" value="hasChoiceNb" - disabled="choiceNbDisabled" - t:mixins="triggerFragment" - t:fragment="choiceNbFragment" /> - <label t:type="label" t:for="choiceNb" /> - <span t:type="ck/Tooltip" title="message:help" - t:value="message:choiceNb-help" - t:effect="appear"> - <img src="${asset:context:img/help.png}" - alt="message:help" /> - </span> + <input t:type="checkbox" t:id="choiceNb" value="hasChoiceNb" + disabled="choiceNbDisabled" + t:mixins="triggerFragment" + t:fragment="choiceNbFragment" /> + <label t:type="label" t:for="choiceNb" /> + <span t:type="ck/Tooltip" title="message:help" + t:value="message:choiceNb-help" + t:effect="appear"> + <img src="${asset:context:img/help.png}" + alt="message:help" /> + </span> </p> <p> - <t:formFragment id="choiceNbHidden" t:id="choiceNbFragment" - t:visible="hasChoiceNb"> - <label t:type="label" t:for="maxChoiceNb" /> - <input t:type="textfield" t:id="maxChoiceNb" - t:value="poll.maxChoiceNb" t:size="1" - t:validate="min=0" /> - </t:formFragment> + <t:formFragment id="choiceNbHidden" t:id="choiceNbFragment" + t:visible="hasChoiceNb"> + <label t:type="label" t:for="maxChoiceNb" /> + <input t:type="textfield" t:id="maxChoiceNb" + t:value="poll.maxChoiceNb" t:size="1" + t:validate="min=0" /> + </t:formFragment> </p> <p> - <input t:type="checkbox" t:id="sendReminder" - t:value="hasReminder" disabled="reminderDisabled" - t:mixins="triggerfragment" - t:fragment="reminderFragment" /> - <label t:type="label" t:for="sendReminder" /> - <span t:type="ck/Tooltip" title="message:help" - t:value="message:sendReminder-help" - t:effect="appear"> - <img src="${asset:context:img/help.png}" - alt="message:help" /> - </span> + <input t:type="checkbox" t:id="sendReminder" + t:value="hasReminder" disabled="reminderDisabled" + t:mixins="triggerfragment" + t:fragment="reminderFragment" /> + <label t:type="label" t:for="sendReminder" /> + <span t:type="ck/Tooltip" title="message:help" + t:value="message:sendReminder-help" + t:effect="appear"> + <img src="${asset:context:img/help.png}" + alt="message:help" /> + </span> </p> <p> - <t:formFragment id="reminderHidden" t:id="reminderFragment" - t:visible="hasReminder"> - <input t:type="textfield" t:id="reminder" - t:value="reminder.sensibility" t:size="1" - t:validate="min=0" /> - <label t:type="label" t:for="reminder" /> - </t:formFragment> + <t:formFragment id="reminderHidden" t:id="reminderFragment" + t:visible="hasReminder"> + <input t:type="textfield" t:id="reminder" + t:value="reminder.sensibility" t:size="1" + t:validate="min=0" /> + <label t:type="label" t:for="reminder" /> + </t:formFragment> </p> + </div> + <!--</t:formFragment>--> </div> - <!--</t:formFragment>--> + </fieldset> </div> - </fieldset> -</div> -<!-- LISTS --> -<div id="p-pollForm-lists"> - <fieldset> - <legend> - <label t:type="label" t:for="pollType" />: - <!--<select t:type="select" t:id="pollType" class="list-select" t:value="poll.pollType" t:validate="required"--> - <!--t:mixins="nuiton/zoneUpdater" t:event="change" t:zone="p-pollForm-lists-zone" />--> - <select t:type="select" t:id="pollType" t:value="poll.pollType" - t:validate="required" - t:mixins="ck/onEvent" t:event="change" - t:onCompleteCallback="onConfirmRefreshZone" /> - <span t:type="ck/Tooltip" title="message:help" - t:value="message:pollType-help" t:effect="appear"> + <!-- LISTS --> + <div id="p-pollForm-lists"> + <fieldset> + <legend> + <label t:type="label" t:for="pollType" />: + <!--<select t:type="select" t:id="pollType" class="list-select" t:value="poll.pollType" t:validate="required"--> + <!--t:mixins="nuiton/zoneUpdater" t:event="change" t:zone="p-pollForm-lists-zone" />--> + <select t:type="select" t:id="pollType" t:value="poll.pollType" + t:validate="required" + t:mixins="ck/onEvent" t:event="change" + t:onCompleteCallback="onConfirmRefreshZone" /> + <span t:type="ck/Tooltip" title="message:help" + t:value="message:pollType-help" t:effect="appear"> <img src="${asset:context:img/help.png}" alt="message:help" /> - </span> - </legend> - <div t:type="zone" t:id="listsZone" id="p-pollForm-lists-zone" - class="form-block" t:update="show"> - <t:if t:test="canDisplayLists()"> + </span> + </legend> + <div t:type="zone" t:id="listsZone" id="p-pollForm-lists-zone" + class="form-block" t:update="show"> + <t:if t:test="canDisplayLists()"> <t:nuiton.feedback t:id="listsFeedback" /> <br /> <t:subForm t:visible="refreshListsZone"> - <t:if t:test="poll.pollType.group"> - <p> - <label t:type="label" t:for="groupName" />: - <input t:type="textfield" t:id="groupName" - value="listName" /> - <input t:type="submit" t:id="addList" - value="${message:pollen.ui.button.add}" /> - </p> + <t:if t:test="poll.pollType.group"> + <p> + <label t:type="label" t:for="groupName" />: + <input t:type="textfield" t:id="groupName" + value="listName" /> + <input t:type="submit" t:id="addList" + value="${message:pollen.ui.button.add}" /> + </p> - <p class="center"> - <t:loop t:source="lists" t:value="list" - t:encoder="model"> - <input class="list-edition${styleSelected}" - t:type="nuiton/submitContext" - t:context="list.name" t:id="editList" - value="${list.name}" /> - <t:if t:test="currentListSelected"> - <a t:type="actionlink" t:id="removeList" - t:zone="p-pollForm-lists-zone"> - <span t:type="any" - t:mixins="nuiton/confirm"> - <img src="${asset:context:img/delete.png}" - alt="${message:delete}" /> - </span> - </a> - </t:if> - </t:loop> - </p> - </t:if> - <t:if t:test="listSelected"> - <div class="t-data-grid"> - <table class="t-data-grid"> - <thead> - <tr> - <th> - ${message:pollen.ui.participant.name-label} - </th> - <th> - ${message:pollen.ui.participant.email-label} - </th> - <th> - ${message:pollen.ui.participant.weight-label} - </th> - <th></th> - </tr> - </thead> - <tbody> - <tr t:type="ajaxformloop" t:id="participants" - source="listModel.participants" - value="participant" t:encoder="listModel"> - <td> - <t:textfield t:id="participantName" - value="participant.name" - size="20" - t:validate="required" /> - </td> - <td> - <t:textfield t:id="participantEmail" - value="participant.email" - size="25" /> - </td> - <td> - <t:textfield t:id="participantWeight" - value="participant.weight" - size="1" /> - </td> - <td> - <t:removerowlink> - <img src="${asset:context:img/delete.png}" - alt="${message:delete}" /> - </t:removerowlink> - </td> - <p:addRow> - <td colspan="4" class="center"> - <t:addrowlink> - ${message:pollen.ui.participant.add} - </t:addrowlink> - </td> - </p:addRow> - </tr> - </tbody> - </table> - </div> - </t:if> + <p class="center"> + <t:loop t:source="lists" t:value="list" + t:encoder="model"> + <input class="list-edition${styleSelected}" + t:type="nuiton/submitContext" + t:context="list.name" t:id="editList" + value="${list.name}" /> + <t:if t:test="currentListSelected"> + <a t:type="actionlink" t:id="removeList" + t:zone="p-pollForm-lists-zone"> + <span t:type="any" + t:mixins="nuiton/confirm"> + <img src="${asset:context:img/delete.png}" + alt="${message:delete}" /> + </span> + </a> + </t:if> + </t:loop> + </p> + </t:if> + <t:if t:test="listSelected"> + <div class="t-data-grid"> + <table class="t-data-grid"> + <thead> + <tr> + <th> + ${message:pollen.ui.participant.name-label} + </th> + <th> + ${message:pollen.ui.participant.email-label} + </th> + <th> + ${message:pollen.ui.participant.weight-label} + </th> + <th></th> + </tr> + </thead> + <tbody> + <tr t:type="ajaxformloop" t:id="participants" + source="listModel.participants" + value="participant" t:encoder="listModel"> + <td> + <t:textfield t:id="participantName" + value="participant.name" + size="20" + t:validate="required" /> + </td> + <td> + <t:textfield t:id="participantEmail" + value="participant.email" + size="25" /> + </td> + <td> + <t:textfield t:id="participantWeight" + value="participant.weight" + size="1" /> + </td> + <td> + <t:removerowlink> + <img src="${asset:context:img/delete.png}" + alt="${message:delete}" /> + </t:removerowlink> + </td> + <p:addRow> + <td colspan="4" class="center"> + <t:addrowlink> + ${message:pollen.ui.participant.add} + </t:addrowlink> + </td> + </p:addRow> + </tr> + </tbody> + </table> + </div> + </t:if> </t:subForm> - </t:if> + </t:if> + </div> + </fieldset> + <p class="center"> + <input t:type="submit" t:id="choiceStep" value="CHOICE" /> + </p> </div> - </fieldset> - <p class="center"><input t:type="submit" t:id="choiceStep" value="CHOICE" /> - </p> -</div> -</t:formFragment> -<t:formFragment t:id="choiceFormFragment" t:visible="choiceStep"> + </t:formFragment> + <t:formFragment t:id="choiceFormFragment" t:visible="choiceStep"> - <!-- CHOICES --> - <div id="p-pollForm-choices"> - <fieldset> + <!-- CHOICES --> + <div id="p-pollForm-choices"> + <fieldset> <legend> - <label t:type="label" t:for="choiceType" />: - <select t:type="select" t:id="choiceType" - t:value="poll.choiceType" t:validate="required" - t:mixins="nuiton/zoneUpdater" t:event="change" - t:zone="p-pollForm-choices-zone" /> + <label t:type="label" t:for="choiceType" />: + <select t:type="select" t:id="choiceType" + t:value="poll.choiceType" t:validate="required" + t:mixins="nuiton/zoneUpdater" t:event="change" + t:zone="p-pollForm-choices-zone" /> </legend> <t:zone t:id="choicesZone" id="p-pollForm-choices-zone"> - <t:subForm t:visible="refreshChoicesZone"> - <div t:type="loop" t:source="choices" t:value="choice" - t:volatile="true" class="clearfix"> - <div class="fleft choiceName"> - <t:delegate t:to="choiceTypeBlock" /> - <t:block t:id="choiceText"> - <label t:type="label" t:for="choiceTextField" />: - <input type="text" class="nameField" - t:type="textfield" t:id="choiceTextField" - value="choice.text" /> - </t:block> - <t:block t:id="choiceDate"> - <label t:type="label" t:for="choiceDateField" />: - <input t:type="ck/dateTimeField" - t:id="choiceDateField" - value="choice.date" t:validate="regexp" - t:datePattern="message:date-pattern" - t:timePicker="true" - t:timePickerAdjacent="true" /> - </t:block> - <t:block t:id="choiceImage"> - <label t:type="label" - t:for="choiceImageField" />: - <input type="file" class="nameField" - t:type="upload" t:id="choiceImageField" - value="choice.image" - t:validate="regexp" /> - </t:block> - <t:block t:id="choiceDisplay"> - ${choice.name} - </t:block> - - <t:label t:for="choiceDescription" /> - : - </div> - <div class="fleft"> - <t:textarea cols="34" rows="1" - t:id="choiceDescription" - t:value="choice.description" /> - </div> - </div> - </t:subForm> + <t:subForm t:visible="refreshChoicesZone"> + <div t:type="loop" t:source="choices" t:value="choice" + t:volatile="true" class="clearfix"> + <div class="fleft choiceName"> + <t:delegate t:to="choiceTypeBlock" /> + <t:block t:id="choiceText"> + <label t:type="label" t:for="choiceTextField" />: + <input type="text" class="nameField" + t:type="textfield" t:id="choiceTextField" + value="choice.text" /> + </t:block> + <t:block t:id="choiceDate"> + <label t:type="label" t:for="choiceDateField" />: + <input t:type="ck/dateTimeField" + t:id="choiceDateField" + value="choice.date" t:validate="regexp" + t:datePattern="message:date-pattern" + t:timePicker="true" + t:timePickerAdjacent="true" /> + </t:block> + <t:block t:id="choiceImage"> + <label t:type="label" + t:for="choiceImageField" />: + <input type="file" class="nameField" + t:type="upload" t:id="choiceImageField" + value="choice.image" + t:validate="regexp" /> + </t:block> + <t:block t:id="choiceDisplay"> + ${choice.name} + </t:block> + + <t:label t:for="choiceDescription" /> + : + </div> + <div class="fleft"> + <t:textarea cols="34" rows="1" + t:id="choiceDescription" + t:value="choice.description" /> + </div> + </div> + </t:subForm> </t:zone> - </fieldset> - </div> - <p class="center"> - <input t:type="submit" t:id="mainStep" value="PREVIOUS" /> - <input t:type="submit" t:id="save" value="SAVE" /> - </p> -</t:formFragment> -</form> -</t:zone> + </fieldset> + </div> + <p class="center"> + <input t:type="submit" t:id="mainStep" value="PREVIOUS" /> + <input t:type="submit" t:id="save" value="SAVE" /> + </p> + </t:formFragment> + </form> + </t:zone> </html>