Author: tchemit Date: 2012-06-13 01:53:35 +0200 (Wed, 13 Jun 2012) New Revision: 3460 Url: http://chorem.org/repositories/revision/pollen/3460 Log: refs #592: End date of a poll can be anterior than today refs #593: Disable Dates for choices add does not work refs #595: Can set a negative max choice refs #597: Forbid to have two images with the same name refs #607: Can set negative reminderHourCountdown Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/bean/ChoiceHelper.java trunk/pollen-services/src/main/java/org/chorem/pollen/services/PollenServiceFunctions.java trunk/pollen-ui-struts2/src/main/java/org/chorem/pollen/ui/PollenSession.java trunk/pollen-ui-struts2/src/main/java/org/chorem/pollen/ui/actions/io/GetPollImageChoice.java trunk/pollen-ui-struts2/src/main/java/org/chorem/pollen/ui/actions/poll/AbstractPollForm.java trunk/pollen-ui-struts2/src/main/java/org/chorem/pollen/ui/actions/poll/AddChoice.java trunk/pollen-ui-struts2/src/main/java/org/chorem/pollen/ui/actions/poll/LoadPoll.java trunk/pollen-ui-struts2/src/main/java/org/chorem/pollen/ui/actions/poll/SavePoll.java trunk/pollen-ui-struts2/src/main/resources/i18n/pollen-ui-struts2_en_GB.properties trunk/pollen-ui-struts2/src/main/resources/i18n/pollen-ui-struts2_fr_FR.properties trunk/pollen-ui-struts2/src/main/webapp/WEB-INF/jsp/poll/create.jsp trunk/pollen-ui-struts2/src/main/webapp/js/createPoll.js Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/bean/ChoiceHelper.java =================================================================== --- trunk/pollen-services/src/main/java/org/chorem/pollen/bean/ChoiceHelper.java 2012-06-12 21:30:47 UTC (rev 3459) +++ trunk/pollen-services/src/main/java/org/chorem/pollen/bean/ChoiceHelper.java 2012-06-12 23:53:35 UTC (rev 3460) @@ -22,13 +22,11 @@ */ package org.chorem.pollen.bean; -import com.google.common.base.Function; import com.google.common.collect.Iterables; import org.chorem.pollen.business.persistence.Choice; import org.chorem.pollen.common.ChoiceType; +import org.chorem.pollen.services.PollenServiceFunctions; -import java.util.Date; - /** * Used to manage all objects from {@link Choice} inheritance tree depends * on {@link ChoiceType}. @@ -43,43 +41,48 @@ private ChoiceHelper() { } - public static Object toValue(Choice choice, ChoiceType choiceType) { - Object result; - switch (choiceType) { - case DATE: - if (choice instanceof PollDateChoice) { - result = ((PollDateChoice) choice).getDate(); - } else { - result = new Date(Long.parseLong(choice.getName())); - } - break; - case IMAGE: - if (choice instanceof PollImageChoice) { - result = ((PollImageChoice) choice).getLocation(); - } else { - result = choice.getName(); - } - break; - case TEXT: - default: - result = choice.getName(); - } - return result; - } +// public static Object toValue(Choice choice, ChoiceType choiceType) { +// Object result; +// switch (choiceType) { +// case DATE: +// if (choice instanceof PollDateChoice) { +// result = ((PollDateChoice) choice).getDate(); +// } else { +// result = new Date(Long.parseLong(choice.getName())); +// } +// break; +// case IMAGE: +// if (choice instanceof PollImageChoice) { +// result = ((PollImageChoice) choice).getLocation(); +// } else { +// result = choice.getName(); +// } +// break; +// case TEXT: +// default: +// result = choice.getName(); +// } +// return result; +// } - public static Function<Choice, Object> toValue(final ChoiceType type) { - return new Function<Choice, Object>() { +// public static Function<Choice, Object> toValue(final ChoiceType type) { +// return new Function<Choice, Object>() { +// +// @Override +// public Object apply(Choice input) { +// return toValue(input, type); +// } +// }; +// } - @Override - public Object apply(Choice input) { - return toValue(input, type); - } - }; - } +// public static Iterable<Object> toValues(Iterable<Choice> choices, +// ChoiceType choiceType) { +// return Iterables.transform(choices, toValue(choiceType)); +// } - public static Iterable<Object> toValues(Iterable<Choice> choices, - ChoiceType choiceType) { - return Iterables.transform(choices, toValue(choiceType)); + public static Iterable<String> toNames(Iterable<Choice> choices) { + return Iterables.transform(choices, + PollenServiceFunctions.CHOICE_TO_NAME); } public static String getValuePropertyName(ChoiceType choiceType) { Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/PollenServiceFunctions.java =================================================================== --- trunk/pollen-services/src/main/java/org/chorem/pollen/services/PollenServiceFunctions.java 2012-06-12 21:30:47 UTC (rev 3459) +++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/PollenServiceFunctions.java 2012-06-12 23:53:35 UTC (rev 3460) @@ -73,6 +73,13 @@ } } + public static final Function<Choice, String> CHOICE_TO_NAME = new Function<Choice, String>() { + @Override + public String apply(Choice input) { + return input.getName(); + } + }; + public static TopiaIdExtractor newTopiaIdExtractor() { return new TopiaIdExtractor(); } Modified: trunk/pollen-ui-struts2/src/main/java/org/chorem/pollen/ui/PollenSession.java =================================================================== --- trunk/pollen-ui-struts2/src/main/java/org/chorem/pollen/ui/PollenSession.java 2012-06-12 21:30:47 UTC (rev 3459) +++ trunk/pollen-ui-struts2/src/main/java/org/chorem/pollen/ui/PollenSession.java 2012-06-12 23:53:35 UTC (rev 3460) @@ -32,6 +32,7 @@ import javax.servlet.ServletRequest; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; +import java.util.Iterator; import java.util.List; import java.util.Map; @@ -151,4 +152,15 @@ messages.add(message); } } + + public void removeDynamicDataWithPrefix(String prefix) { + Iterator<Map.Entry<String, Object>> itr = + getDynamicData().entrySet().iterator(); + while (itr.hasNext()) { + Map.Entry<String, Object> entry = itr.next(); + if (entry.getKey().startsWith(prefix)) { + itr.remove(); + } + } + } } Modified: trunk/pollen-ui-struts2/src/main/java/org/chorem/pollen/ui/actions/io/GetPollImageChoice.java =================================================================== --- trunk/pollen-ui-struts2/src/main/java/org/chorem/pollen/ui/actions/io/GetPollImageChoice.java 2012-06-12 21:30:47 UTC (rev 3459) +++ trunk/pollen-ui-struts2/src/main/java/org/chorem/pollen/ui/actions/io/GetPollImageChoice.java 2012-06-12 23:53:35 UTC (rev 3460) @@ -85,7 +85,7 @@ if (StringUtils.isNotBlank(choiceTokenId)) { // use location from session - file = getPollenSession().consumeDynamicData(choiceTokenId); + file = getPollenSession().getDynamicData(choiceTokenId); } else { // using pollId / choiceId to find image to render Modified: trunk/pollen-ui-struts2/src/main/java/org/chorem/pollen/ui/actions/poll/AbstractPollForm.java =================================================================== --- trunk/pollen-ui-struts2/src/main/java/org/chorem/pollen/ui/actions/poll/AbstractPollForm.java 2012-06-12 21:30:47 UTC (rev 3459) +++ trunk/pollen-ui-struts2/src/main/java/org/chorem/pollen/ui/actions/poll/AbstractPollForm.java 2012-06-12 23:53:35 UTC (rev 3460) @@ -59,6 +59,8 @@ private static final long serialVersionUID = 1L; + public static final String IMAGECHOICES_THUMB_PREFIX = "imagechoicesThumb_"; + protected Poll poll; private Map<String, String> pollTypes; @@ -88,8 +90,10 @@ private boolean limitChoice; - private int reminderHourCountdown = 2; + private Integer maxChoices; + private Integer reminderHourCountdown; + /** To create a new personToList. */ private transient Function<PersonToList, PersonToList> persontoListCreator; @@ -162,6 +166,14 @@ this.notification = notification; } + public Integer getMaxChoices() { + return maxChoices; + } + + public void setMaxChoices(Integer maxChoices) { + this.maxChoices = maxChoices; + } + public boolean isReminder() { return reminder; } @@ -178,11 +190,11 @@ this.limitChoice = limitChoice; } - public int getReminderHourCountdown() { + public Integer getReminderHourCountdown() { return reminderHourCountdown; } - public void setReminderHourCountdown(int reminderHourCountdown) { + public void setReminderHourCountdown(Integer reminderHourCountdown) { this.reminderHourCountdown = reminderHourCountdown; } @@ -196,18 +208,6 @@ return pollType == PollType.GROUP; } -// public String getPollVoteUrl() { -// return getPollUrlService().getPollVoteUrl(poll, false).getUrl(); -// } -// -// public String getPollModerateUrl() { -// return getPollUrlService().getPollVoteUrl(poll, true).getUrl(); -// } -// -// public String getPollEditUrl() { -// return getPollUrlService().getPollEditUrl(poll).getUrl(); -// } - public int getSelectedTab() { int result = 0; return result; @@ -238,6 +238,8 @@ public void prepareFormPage() throws Exception { + getPollenSession().removeDynamicDataWithPrefix(IMAGECHOICES_THUMB_PREFIX); + pollTypes = decorateToName(PollType.values()); choiceTypes = decorateToName(ChoiceType.values()); voteCountingTypes = decorateToName(VoteCountingType.values()); @@ -349,7 +351,7 @@ // keep in session the location of this thumb (do not // want to expose the full path location in url) getPollenSession().putDynamicData( - "imagechoicesThumb_" + choice.getName(), + IMAGECHOICES_THUMB_PREFIX + choice.getName(), thumbFile); } Modified: trunk/pollen-ui-struts2/src/main/java/org/chorem/pollen/ui/actions/poll/AddChoice.java =================================================================== --- trunk/pollen-ui-struts2/src/main/java/org/chorem/pollen/ui/actions/poll/AddChoice.java 2012-06-12 21:30:47 UTC (rev 3459) +++ trunk/pollen-ui-struts2/src/main/java/org/chorem/pollen/ui/actions/poll/AddChoice.java 2012-06-12 23:53:35 UTC (rev 3460) @@ -97,22 +97,21 @@ String propName = ChoiceHelper.getValuePropertyName(choiceType); - Object value = ChoiceHelper.toValue(choice, choiceType); + String choiceName = choice.getName(); // -- Validate value notEmpty - if (value == null || - (value instanceof String && StringUtils.isBlank((String) value))) { + if (StringUtils.isBlank(choiceName)) { String typeLabel = getText(choiceType.getI18nKey()); addFieldError("choice." + propName, _("pollen.error.choice.empty", typeLabel)); } else { // Retrieve existing values to check if the new choice not already exists - Iterable<Object> pollChoiceValues = ChoiceHelper.toValues( - getPoll().getChoice(), choiceType); + Iterable<String> pollChoiceValues = ChoiceHelper.toNames( + getPoll().getChoice()); // -- Validate value notExists - if (Iterables.contains(pollChoiceValues, value)) { + if (Iterables.contains(pollChoiceValues, choiceName)) { addFieldError("choice." + propName, _("pollen.error.poll.detected.duplicate.choice.name")); } Modified: trunk/pollen-ui-struts2/src/main/java/org/chorem/pollen/ui/actions/poll/LoadPoll.java =================================================================== --- trunk/pollen-ui-struts2/src/main/java/org/chorem/pollen/ui/actions/poll/LoadPoll.java 2012-06-12 21:30:47 UTC (rev 3459) +++ trunk/pollen-ui-struts2/src/main/java/org/chorem/pollen/ui/actions/poll/LoadPoll.java 2012-06-12 23:53:35 UTC (rev 3460) @@ -129,11 +129,21 @@ setLimitChoice(poll.getMaxChoiceNb() > 0); + if (isLimitChoice()) { + setMaxChoices(poll.getMaxChoiceNb()); + } else { + // set default max choices + setMaxChoices(1); + } PreventRule reminder = poll.getPreventRuleByScope( PreventRuleService.SCOPE_REMINDER); if (reminder != null) { setReminder(true); setReminderHourCountdown(reminder.getSensibility()); + } else { + setReminder(false); + // set default reminderHourCountdown + setReminderHourCountdown(2); } PreventRule notification = poll.getPreventRuleByScope( Modified: trunk/pollen-ui-struts2/src/main/java/org/chorem/pollen/ui/actions/poll/SavePoll.java =================================================================== --- trunk/pollen-ui-struts2/src/main/java/org/chorem/pollen/ui/actions/poll/SavePoll.java 2012-06-12 21:30:47 UTC (rev 3459) +++ trunk/pollen-ui-struts2/src/main/java/org/chorem/pollen/ui/actions/poll/SavePoll.java 2012-06-12 23:53:35 UTC (rev 3460) @@ -210,7 +210,6 @@ Collection<VotingList> pollVotingLists = isVoteStarted() ? poll.getVotingList() : votingLists.values(); - if (ChoiceType.IMAGE == poll.getChoiceType()) { // recopy images for new choices, the one uploaded will be @@ -278,9 +277,14 @@ } } - // Reset maxChoiceNb if limitChoice is unchecked - if (!isLimitChoice()) { + if (isLimitChoice()) { + + // push back filled value + poll.setMaxChoiceNb(getMaxChoices()); + } else { + // reset value poll.setMaxChoiceNb(0); + } //TODO-tchemit comment me 2012-06-04 A merge would be nicer but more complex to code poll.clearPreventRule(); @@ -391,13 +395,13 @@ _("pollen.error.poll.required.one.choice")); } else { - ChoiceType choiceType = poll.getChoiceType(); - int inputChoicesSize = choices.size(); - Set<Object> choiceValues = - Sets.newHashSet(ChoiceHelper.toValues(choices.values(), - choiceType)); + // get all names from choices + Set<String> choiceNames = + Sets.newHashSet(ChoiceHelper.toNames(choices.values())); - if (inputChoicesSize > choiceValues.size()) { + if (choices.size() > choiceNames.size()) { + + // theire is some duplicated names addInformationsError( "poll.choices", _("pollen.error.poll.detected.duplicate.choice.name")); @@ -437,12 +441,15 @@ } String creatorEmail = poll.getCreator().getEmail(); - if (StringUtils.isNotBlank(creatorEmail) && !StringUtil.isEmail(creatorEmail)) { + if (StringUtils.isNotBlank(creatorEmail) && + !StringUtil.isEmail(creatorEmail)) { addOptionsError("poll.creator.email", _("pollen.error.email.invalid")); } + Date currentTime = serviceContext.getCurrentTime(); + if (validateEndDate(poll.getBeginChoiceDate(), poll.getEndChoiceDate())) { addOptionsError( @@ -450,17 +457,64 @@ _("pollen.error.poll.endChoiceDate.before.beginChoiceDate")); } + if (validateEndDate(currentTime, poll.getEndChoiceDate())) { + + addOptionsError( + "poll.endChoiceDate", + _("pollen.error.poll.endChoiceDate.before.now")); + } + if (validateEndDate(poll.getBeginDate(), poll.getEndDate())) { addOptionsError("poll.endDate", _("pollen.error.poll.endDate.before.beginDate")); } + + if (validateEndDate(currentTime, poll.getEndDate())) { + + addOptionsError( + "poll.endDate", + _("pollen.error.poll.endDate.before.now")); + } + if (validateEndDate(poll.getEndChoiceDate(), poll.getEndDate())) { addOptionsError("poll.endChoiceDate", _("pollen.error.poll.endChoiceDate.after.endDate")); } + + if (isLimitChoice()) { + + // validate maxChoices + + if (getMaxChoices() == null) { + // maxChoices == null + addOptionsError("maxChoices", + _("pollen.error.poll.maxChoice.required")); + } else if (getMaxChoices() < 1) { + // maxChoices <= 0 + addOptionsError("maxChoices", + _("pollen.error.poll.maxChoice.greater.than.0")); + } + } + + if (isReminder()) { + + // validate reminderHourCountdown + + if (getReminderHourCountdown() == null) { + + // reminderHourCountdown == null + addOptionsError("reminderHourCountdown", + _("pollen.error.poll.reminderHourCountdown.required")); + } else if (getReminderHourCountdown() < 1) { + + // reminderHourCountdown <= 0 + addOptionsError("reminderHourCountdown", + _("pollen.error.poll.reminderHourCountdown.greater.than.0")); + } + } } protected void validateVotingList(int votingListNumber, Modified: trunk/pollen-ui-struts2/src/main/resources/i18n/pollen-ui-struts2_en_GB.properties =================================================================== --- trunk/pollen-ui-struts2/src/main/resources/i18n/pollen-ui-struts2_en_GB.properties 2012-06-12 21:30:47 UTC (rev 3459) +++ trunk/pollen-ui-struts2/src/main/resources/i18n/pollen-ui-struts2_en_GB.properties 2012-06-12 23:53:35 UTC (rev 3460) @@ -150,7 +150,6 @@ pollen.common.voterName=Votant pollen.common.votingList=Group pollen.common.weight=Weight -pollen.error.accountNotFound= pollen.error.choice.empty=%s mandatory pollen.error.comment.name.empty=Comment name mandatory pollen.error.comment.text.empty=Comment text mandatory @@ -174,11 +173,17 @@ pollen.error.poll.detected.duplicate.choice.name=Choices must be unique. pollen.error.poll.endChoiceDate.after.endDate=The choice end date must be sooner than the poll end date. pollen.error.poll.endChoiceDate.before.beginChoiceDate=The choice end date must be later than the begin date. +pollen.error.poll.endChoiceDate.before.now=The choice end date must be later than current date. pollen.error.poll.endDate.before.beginDate=The poll end date must be later than the begin date. +pollen.error.poll.endDate.before.now=The poll end date must be later than current date. +pollen.error.poll.maxChoice.greater.than.0=Number of choices must be strictly greater than 0 +pollen.error.poll.maxChoice.required=Number of choices mandatory pollen.error.poll.notfound=No such poll exists. Please make sure that you are using the correct link and copy it completely into your browser's address field. pollen.error.poll.personToList.email.doublon=Email must be unique pollen.error.poll.personToList.votingId.doublon=The voter's name must be unique -pollen.error.poll.personToList.weight.not.valid=The voter's weight is not valid (must be greater than 0) +pollen.error.poll.personToList.weight.not.valid=The voter's weight is not valid (must be greater than 0). +pollen.error.poll.reminderHourCountdown.greater.than.0=Reminder hour countdown must be strictly greater than 0. +pollen.error.poll.reminderHourCountdown.required=Reminder hour countdown mandatory. pollen.error.poll.required.one.choice=You must provide at least one choice pollen.error.poll.required.one.personToList=You must provide at least one voter pollen.error.poll.required.title=You must provide a title for the poll Modified: trunk/pollen-ui-struts2/src/main/resources/i18n/pollen-ui-struts2_fr_FR.properties =================================================================== --- trunk/pollen-ui-struts2/src/main/resources/i18n/pollen-ui-struts2_fr_FR.properties 2012-06-12 21:30:47 UTC (rev 3459) +++ trunk/pollen-ui-struts2/src/main/resources/i18n/pollen-ui-struts2_fr_FR.properties 2012-06-12 23:53:35 UTC (rev 3460) @@ -150,7 +150,6 @@ pollen.common.voterName=Votant pollen.common.votingList=Groupe pollen.common.weight=Poids -pollen.error.accountNotFound= pollen.error.choice.empty=%s obligatoire pollen.error.comment.name.empty=Nom du commentaire obligatoire pollen.error.comment.text.empty=Texte du commentaire obligatoire @@ -174,11 +173,17 @@ pollen.error.poll.detected.duplicate.choice.name=Les choix doivent être uniques. pollen.error.poll.endChoiceDate.after.endDate=La date de fin d'ajout de choix doit-être antérieure à la date de fin du sondage. pollen.error.poll.endChoiceDate.before.beginChoiceDate=La date de fin d'ajout de choix doit-être postérieure à la date de début. +pollen.error.poll.endChoiceDate.before.now=La date de fin d'ajout de choix doit-être postérieure à la date actuelle. pollen.error.poll.endDate.before.beginDate=La date de fin du sondage doit-être postérieure à la date de début. +pollen.error.poll.endDate.before.now=La date de fin du sondage doit-être postérieure à la date actuelle. +pollen.error.poll.maxChoice.greater.than.0=Nombre de choix maximum doit être strictement supérieur à 0 +pollen.error.poll.maxChoice.required=Nombre de choix maximum obligatoire pollen.error.poll.notfound=Il n'y a pas de sondage à cette adresse. Veuillez verifier que vous utilisez le lien correcte et copiez-le complètement dans le champ d'adresse de votre navigateur. pollen.error.poll.personToList.email.doublon=Les emails doivent être uniques. pollen.error.poll.personToList.votingId.doublon=Les noms des votants doivent être uniques. pollen.error.poll.personToList.weight.not.valid=Poids du votant non valide (doit être une nombre supérieur à 0). +pollen.error.poll.reminderHourCountdown.greater.than.0=Le nombre d'heures doit être strictement supérieure à 0. +pollen.error.poll.reminderHourCountdown.required=Le nombre d'heures est obligatoire. pollen.error.poll.required.one.choice=Vous devez saisir au moins un choix. pollen.error.poll.required.one.personToList=Aucun votant renseigné pollen.error.poll.required.title=Vous devez fournir un titre pour le sondage Modified: trunk/pollen-ui-struts2/src/main/webapp/WEB-INF/jsp/poll/create.jsp =================================================================== --- trunk/pollen-ui-struts2/src/main/webapp/WEB-INF/jsp/poll/create.jsp 2012-06-12 21:30:47 UTC (rev 3459) +++ trunk/pollen-ui-struts2/src/main/webapp/WEB-INF/jsp/poll/create.jsp 2012-06-12 23:53:35 UTC (rev 3460) @@ -104,6 +104,7 @@ <legend> <s:text name="pollen.common.voteCountingType"/> <img src="<s:url value='/img/tooltip.png'/>" class="tooltip" + alt="<s:text name='pollen.common.voteCountingType.help'/>" title="<s:text name='pollen.common.voteCountingType.help'/>"/> </legend> <s:radio key='poll.voteCountingType' list="voteCountingTypes" @@ -176,7 +177,7 @@ tooltip="%{getText('pollen.common.pollOption.limitChoice.help')}" tooltipIconPath="/img/tooltip.png"/> <div id='maxChoiceNbPanel' class="hidden"> - <s:textfield key="poll.maxChoiceNb" + <s:textfield key="maxChoices" label="%{getText('pollen.common.pollOption.maxChoiceNb')}" disabled="%{voteStarted}"/> </div> @@ -215,7 +216,8 @@ <legend> <s:text name="pollen.common.pollType"/> <img src="<s:url value='/img/tooltip.png'/>" class="tooltip" - title="<s:text name='pollen.common.pollType.help'/>"/> + title="<s:text name='pollen.common.pollType.help'/>" + alt="<s:text name='pollen.common.pollType.help'/>"/> </legend> <s:radio key='poll.pollType' list="pollTypes" label='%{getText("pollen.common.pollType")}' Modified: trunk/pollen-ui-struts2/src/main/webapp/js/createPoll.js =================================================================== --- trunk/pollen-ui-struts2/src/main/webapp/js/createPoll.js 2012-06-12 21:30:47 UTC (rev 3459) +++ trunk/pollen-ui-struts2/src/main/webapp/js/createPoll.js 2012-06-12 23:53:35 UTC (rev 3460) @@ -563,6 +563,8 @@ } else { $('#addChoiceAddAllowedPanel').hide(); } + $('[name="poll.beginChoiceDate"],[name="poll.endChoiceDate"]').attr( + 'disabled', !val); } function changeLimitChoice(val) { @@ -571,6 +573,7 @@ } else { $('#maxChoiceNbPanel').hide(); } + $('[name="maxChoices"]').attr('disabled', !val); } function changeReminder(val) { @@ -579,6 +582,7 @@ } else { $('#reminderPanel').hide(); } + $('[name="reminderHourCountdown"]').attr('disabled', !val); } function changePollType(type) {