r3494 - in trunk/pollen-ui-struts2/src: main/java/org/chorem/pollen/ui/actions/json main/java/org/chorem/pollen/ui/actions/poll main/java/org/chorem/pollen/ui/security main/resources main/resources/config main/resources/i18n main/webapp/WEB-INF/decorators main/webapp/WEB-INF/jsp main/webapp/WEB-INF/jsp/poll test/java/org/chorem/pollen/ui test/java/org/chorem/pollen/ui/its
Author: tchemit Date: 2012-06-16 22:36:03 +0200 (Sat, 16 Jun 2012) New Revision: 3494 Url: http://chorem.org/repositories/revision/pollen/3494 Log: fixes #608: Cannot access vote results fixes #599: Can submit a participant with no name, but it is not saved fixes #600: Cannot have several particpant: all became one, duplicated on each line fixes #602: In creation, a member of a group can be created without name fixes #618: Improve poll form url workflow refs #609: Review security access for administrator refs #612: Review security access for creator Added: trunk/pollen-ui-struts2/src/main/java/org/chorem/pollen/ui/actions/poll/ClonePoll.java trunk/pollen-ui-struts2/src/main/java/org/chorem/pollen/ui/actions/poll/CreatePoll.java trunk/pollen-ui-struts2/src/main/java/org/chorem/pollen/ui/actions/poll/EditPoll.java Removed: 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/webapp/WEB-INF/jsp/poll/resultLink.jsp Modified: trunk/pollen-ui-struts2/src/main/java/org/chorem/pollen/ui/actions/json/GetCreatedPolls.java trunk/pollen-ui-struts2/src/main/java/org/chorem/pollen/ui/actions/json/GetPollComments.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/AbstractVoteAction.java trunk/pollen-ui-struts2/src/main/java/org/chorem/pollen/ui/actions/poll/SummaryPoll.java trunk/pollen-ui-struts2/src/main/java/org/chorem/pollen/ui/actions/poll/VoteForPoll.java trunk/pollen-ui-struts2/src/main/java/org/chorem/pollen/ui/security/PollResultAccessRequired.java trunk/pollen-ui-struts2/src/main/resources/config/struts-poll.xml 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/resources/shiro.ini trunk/pollen-ui-struts2/src/main/webapp/WEB-INF/decorators/layout-default.jsp trunk/pollen-ui-struts2/src/main/webapp/WEB-INF/jsp/home.jsp trunk/pollen-ui-struts2/src/main/webapp/WEB-INF/jsp/poll/create.jsp trunk/pollen-ui-struts2/src/main/webapp/WEB-INF/jsp/poll/createPoll_choices.jsp trunk/pollen-ui-struts2/src/main/webapp/WEB-INF/jsp/poll/result.jsp trunk/pollen-ui-struts2/src/main/webapp/WEB-INF/jsp/poll/summary.jsp trunk/pollen-ui-struts2/src/test/java/org/chorem/pollen/ui/PollenFixtures.java trunk/pollen-ui-struts2/src/test/java/org/chorem/pollen/ui/its/CreateFreeTextPollSIT.java trunk/pollen-ui-struts2/src/test/java/org/chorem/pollen/ui/its/SecurityAccessSIT.java Modified: trunk/pollen-ui-struts2/src/main/java/org/chorem/pollen/ui/actions/json/GetCreatedPolls.java =================================================================== --- trunk/pollen-ui-struts2/src/main/java/org/chorem/pollen/ui/actions/json/GetCreatedPolls.java 2012-06-16 20:33:49 UTC (rev 3493) +++ trunk/pollen-ui-struts2/src/main/java/org/chorem/pollen/ui/actions/json/GetCreatedPolls.java 2012-06-16 20:36:03 UTC (rev 3494) @@ -24,14 +24,12 @@ import com.google.common.collect.Sets; import org.chorem.pollen.business.persistence.Poll; -import org.chorem.pollen.common.PollType; import org.chorem.pollen.entities.PollenBinderHelper; import org.chorem.pollen.services.impl.PollService; import org.nuiton.util.beans.Binder; import java.util.List; import java.util.Map; -import java.util.Set; /** * Obtain created polls to put in grid for the connected user. @@ -86,28 +84,12 @@ Map<String, Object> map = pollService.pollToMap(poll, binder); - map.put("voteId", poll.getPollId()); +// map.put("voteId", poll.getPollId()); map.put("adminId", poll.getAdminId()); - Set<String> functions = getPollFunctions(poll); - map.put("functions", functions); + map.put("functions", Sets.newHashSet("summary")); polls[index++] = map; } return SUCCESS; } - protected Set<String> getPollFunctions(Poll poll) { - Set<String> result = Sets.newHashSet(); - if (PollType.FREE == poll.getPollType()) { - - // only free poll could have vote action because creator can't vote - result.add("vote"); - } else { - // to be sure a blank image is setted instead of vote picto - result.add("novote"); - } - result.add("summary"); - result.add("delete"); - return result; - } - } Modified: trunk/pollen-ui-struts2/src/main/java/org/chorem/pollen/ui/actions/json/GetPollComments.java =================================================================== --- trunk/pollen-ui-struts2/src/main/java/org/chorem/pollen/ui/actions/json/GetPollComments.java 2012-06-16 20:33:49 UTC (rev 3493) +++ trunk/pollen-ui-struts2/src/main/java/org/chorem/pollen/ui/actions/json/GetPollComments.java 2012-06-16 20:36:03 UTC (rev 3494) @@ -111,7 +111,7 @@ UserAccount userAccount) { Set<String> result = Sets.newHashSet(); //TODO-tchemit-2012-06-03 Should use also pollAccountId (if specified in url)... - boolean canDelete = getPollCommentService().isCanDeleteComment( + boolean canDelete = getSecurityService().isCanDeleteComment( comment, null, userAccount, false); if (canDelete) { result.add("delete"); 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-16 20:33:49 UTC (rev 3493) +++ trunk/pollen-ui-struts2/src/main/java/org/chorem/pollen/ui/actions/poll/AbstractPollForm.java 2012-06-16 20:36:03 UTC (rev 3494) @@ -24,30 +24,57 @@ import com.google.common.base.Function; import com.google.common.base.Preconditions; +import com.google.common.base.Predicate; import com.google.common.collect.Lists; import com.google.common.collect.Maps; +import com.google.common.collect.Sets; +import com.opensymphony.xwork2.Preparable; +import com.opensymphony.xwork2.interceptor.annotations.InputConfig; import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections.MapUtils; +import org.apache.commons.io.FileUtils; import org.apache.commons.lang3.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.struts2.interceptor.ParameterAware; +import org.chorem.pollen.bean.PollDateChoice; import org.chorem.pollen.bean.PollImageChoice; +import org.chorem.pollen.bean.PollUri; import org.chorem.pollen.business.persistence.Choice; +import org.chorem.pollen.business.persistence.ChoiceImpl; import org.chorem.pollen.business.persistence.PersonToList; +import org.chorem.pollen.business.persistence.PersonToListImpl; import org.chorem.pollen.business.persistence.Poll; import org.chorem.pollen.business.persistence.PollAccount; +import org.chorem.pollen.business.persistence.PollAccountImpl; +import org.chorem.pollen.business.persistence.PreventRule; +import org.chorem.pollen.business.persistence.UserAccount; import org.chorem.pollen.business.persistence.VotingList; +import org.chorem.pollen.business.persistence.VotingListImpl; import org.chorem.pollen.common.ChoiceType; import org.chorem.pollen.common.I18nAble; import org.chorem.pollen.common.PollType; import org.chorem.pollen.common.VoteCountingType; import org.chorem.pollen.services.PollenServiceFunctions; +import org.chorem.pollen.services.exceptions.PollNotFoundException; import org.chorem.pollen.services.impl.PollService; +import org.chorem.pollen.services.impl.PreventRuleService; +import org.chorem.pollen.ui.actions.FileUploadAware; import org.chorem.pollen.ui.actions.PageSkin; import org.chorem.pollen.ui.actions.PollenActionSupport; +import org.chorem.pollen.ui.converters.DateConverter; +import org.nuiton.util.StringUtil; import java.io.File; import java.io.IOException; import java.util.Collection; +import java.util.Collections; +import java.util.Date; import java.util.List; import java.util.Map; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; /** * Created: 04/04/12 @@ -55,12 +82,24 @@ * @author fdesbois <desbois@codelutin.com> * $Id$ */ -public abstract class AbstractPollForm extends PollenActionSupport { +public abstract class AbstractPollForm extends PollenActionSupport implements Preparable, ParameterAware, FileUploadAware { private static final long serialVersionUID = 1L; + /** Logger. */ + private static final Log log = LogFactory.getLog(AbstractPollForm.class); + public static final String IMAGECHOICES_THUMB_PREFIX = "imagechoicesThumb_"; + private static final Pattern TEXT_CHOICE_NAME_PATTERN = + Pattern.compile("textChoice_(\\d+)\\.name"); + + private static final Pattern DATE_CHOICE_NAME_PATTERN = + Pattern.compile("dateChoice_(\\d+)\\.name"); + + private static final Pattern IMAGE_CHOICE_DESCRIPTION_PATTERN = + Pattern.compile("imageChoice_(\\d+)\\.description"); + protected Poll poll; private Map<String, String> pollTypes; @@ -109,23 +148,415 @@ /** To create a new image choice. */ private transient Function<Choice, Choice> imageChoiceCreator; + /** + * Flag when there is some errors on the information panel. + * + * @since 1.3 + */ + protected boolean informationsError; + + /** + * Flag when there is some errors on the options panel. + * + * @since 1.3 + */ + private boolean optionsError; + + /** + * All the parameters send by request used to build back choices of the + * poll. + * + * @since 1.3 + */ + protected final Map<String, String[]> parameters = Maps.newTreeMap(); + + /** + * Indexed choices retreive from parameters for the choiceType selected in + * form. (Other choices are lost). + * + * @since 1.3 + */ + private Map<Integer, Choice> choices; + + /** + * Indexed voting lists retreive from parameters for the pollType selected + * in form. (Other voting lists are lost). + * + * @since 1.3 + */ + private Map<Integer, VotingList> votingLists; + + private PollUri pollUri; + + public abstract boolean isClone(); + + protected abstract Poll savePoll(Poll poll) throws PollNotFoundException; + + public abstract boolean isEdit(); + @Override + public void prepare() throws Exception { + + prepareFormPage(); + + if (parameters.containsKey("poll.title")) { + + if (log.isInfoEnabled()) { + log.info("Starts prepare form..."); + } + + // we are after a submit + + String pollUid = getNonEmptyParameterValue("poll.pollId"); + String userId = getNonEmptyParameterValue("userId"); + if (StringUtils.isBlank(userId)) { + + // try to take the one from current user + UserAccount userAccount = getPollenUserAccount(); + if (userAccount != null) { + userId = userAccount.getTopiaId(); + } + } + UserAccount userAccount = null; + if (StringUtils.isNotBlank(userId)) { + // load use account to use + userAccount = getPollService().getEntityById( + UserAccount.class, userId); + } + + // get a copy (or a fresh new poll) + poll = getPollService().getPollEditable(pollUid, userAccount, false); + + // If vote is started, prepare choices and votingLists is useless + // because they can't be updated. + if (!isVoteStarted()) { + + // Retrieve choiceType from parameters, the poll object will be updated after prepare + String choiceTypeParam = getNonEmptyParameterValue("poll.choiceType"); + ChoiceType pollChoiceType = ChoiceType.valueOf(choiceTypeParam); + poll.setChoiceType(pollChoiceType); + + // build poll choices + + switch (pollChoiceType) { + + case TEXT: + choices = buildTextChoices(); + break; + case DATE: + choices = buildDateChoices(); + break; + case IMAGE: + choices = buildImageChoices(); + break; + } + PollType pollType; + String pollTypeParam = getNonEmptyParameterValue("poll.pollType"); + pollType = PollType.valueOf(pollTypeParam); + switch (pollType) { + + case FREE: + + // empty voting list + votingLists = Maps.newTreeMap(); + break; + case RESTRICTED: + + // restricted voting list + votingLists = buildVotingLists(pollType); + break; + case GROUP: + + // group voting lists + votingLists = buildVotingLists(pollType); + break; + } + } + } + } + + @Override + public String input() throws Exception { + + prepareFormPage(); + + UserAccount userAccount = getPollenUserAccount(); + String pollUid = pollUri == null ? null : pollUri.getPollId(); + PollService service = getPollService(); + + poll = service.getPollEditable(pollUid, userAccount, isClone()); + + if (poll.isClosed()) { + addFlashWarning(_("pollen.warning.poll.is.closed.so.read.only")); + } + List<Choice> pollChoices = poll.getChoice(); + + if (isClone()) { + + if (ChoiceType.IMAGE == poll.getChoiceType()) { + + // recopy images to tmp + + File tmpDir = getConfiguration().getTemporaryDirectory(); + for (Choice choice : pollChoices) { + String choiceName = choice.getName(); + + // image from poll to clone + File imageChoiceFile = service.getPollChoiceImageFile( + pollUid, + choiceName + ); + + // new image + File newImageChoiceFile = File.createTempFile( + choiceName, null, tmpDir); + + if (log.isInfoEnabled()) { + log.info("Copy image from " + imageChoiceFile + + " to " + newImageChoiceFile); + } + FileUtils.copyFile(imageChoiceFile, + newImageChoiceFile); + + ((PollImageChoice) choice).setLocation( + newImageChoiceFile.getAbsolutePath()); + } + } + } + + List<VotingList> pollVotingLists = poll.getVotingList(); + + loadChoicesAndvotingLists(poll, + pollChoices, + pollVotingLists, + !isVoteStarted()); + + 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( + PreventRuleService.SCOPE_VOTE); + if (notification != null) { + setNotification(true); + } + + if (isVoteStarted()) { + addFlashMessage(_("pollen.information.poll.form.voteStarted")); + } + + return INPUT; + } + + public String inputAfterValidationError() throws Exception { + + Collection<Choice> pollChoices = + isVoteStarted() ? poll.getChoice() : choices.values(); + Collection<VotingList> pollVotingLists = + isVoteStarted() ? poll.getVotingList() : votingLists.values(); + + if (ChoiceType.IMAGE == poll.getChoiceType()) { + + // recopy images for new choices, the one uploaded will be + // destroyed, by the upload interceptor + + File tmpDir = getConfiguration().getTemporaryDirectory(); + + for (Choice choice : pollChoices) { + + PollImageChoice imageChoice = (PollImageChoice) choice; + + String choiceId = choice.getTopiaId(); + String location = imageChoice.getLocation(); + + if (StringUtils.isBlank(choiceId) && + !isImageUploadEmpty(imageChoice)) { + + // not persisted choice with an upload + // let's copy it somewhere safe + + File uploadedImage = new File(location); + File copyImage = File.createTempFile( + uploadedImage.getName(), null, tmpDir); + + if (log.isInfoEnabled()) { + log.info("Copy image from " + uploadedImage + + " to " + copyImage); + } + FileUtils.copyFile(uploadedImage, copyImage); + + imageChoice.setLocation(copyImage.getAbsolutePath()); + } + } + } + + loadChoicesAndvotingLists(poll, pollChoices, pollVotingLists, true); + return INPUT; + } + + @Override + @InputConfig(methodName = "inputAfterValidationError") + public String execute() throws Exception { + + // Save choices and votingLists only if vote is not started + if (!isVoteStarted()) { + //TODO-tchemit comment me 2012-06-04 A merge would be nicer but more complex to code + // Clear previous collections to save those from the form + poll.clearChoice(); + poll.clearVotingList(); + for (Integer index : choices.keySet()) { + Choice choice = choices.get(index); + poll.addChoice(choice); + } + + if (!isFreePoll()) { + + for (Integer index : votingLists.keySet()) { + VotingList votingList = votingLists.get(index); + poll.addVotingList(votingList); + } + } + } + + if (isLimitChoice()) { + + // push back filled value + poll.setMaxChoiceNb(getMaxChoices()); + } else { + // reset value + poll.setMaxChoiceNb(0); + } + + if (!poll.isPublicResults()) { + + // force to not have continous results + poll.setContinuousResults(false); + } + + if (poll.isAnonymous()) { + + // force to not have choice to vote anonymously + poll.setAnonymousVoteAllowed(false); + } + + //TODO-tchemit comment me 2012-06-04 A merge would be nicer but more complex to code + poll.clearPreventRule(); + + PreventRuleService preventRuleService = getPreventRuleService(); + if (isNotification()) { + + // add a notification rule + + PreventRule rule = preventRuleService.createAddVotePreventRule(); + poll.addPreventRule(rule); + } + + if (isReminder()) { + + // add a reminder rule + + PreventRule rule = preventRuleService.createRemindPreventRule( + getReminderHourCountdown() + ); + + poll.addPreventRule(rule); + } + + // do save poll + poll = savePoll(poll); + + // compute fresh pollUri + pollUri = PollUri.newPollUri(poll.getAdminId()); + + // remove all stuff from session + getPollenSession().clearDynamicData(); + + return SUCCESS; + } + + @Override + public void validate() { + + validateInformations(); + + validateOptions(); + } + + @Override + public void addFile(int index, File file) { + parameters.put("imageChoice_" + index + ".newLocation", + new String[]{file.getAbsolutePath()}); + } + + @Override + public void addFileContentType(int index, String contentType) { + // not used here + } + + @Override + public void addFileName(int index, String fileName) { + parameters.put("imageChoice_" + index + ".newName", new String[]{fileName}); + } + + @Override + public void setParameters(Map<String, String[]> parameters) { + this.parameters.putAll(parameters); + } + + @Override public PageSkin getSkin() { return PageSkin.EDITION; } - public Poll getPoll() { - return poll; - } - public boolean isInformationsError() { - return false; + return informationsError; } public boolean isOptionsError() { - return false; + return optionsError; } + public int getSelectedTab() { + int result; + if (isInformationsError()) { + result = 0; + } else { + if (isOptionsError()) { + result = 1; + } else { + result = 0; + } + } + return result; + } + + public PollUri getUriId() { + return pollUri; + } + + public void setUriId(PollUri pollUri) { + this.pollUri = pollUri; + } + + public Poll getPoll() { + return poll; + } + public Map<String, String> getPollTypes() { return pollTypes; } @@ -208,11 +639,6 @@ return pollType == PollType.GROUP; } - public int getSelectedTab() { - int result = 0; - return result; - } - public String getActionLabel() { return isEdit() ? _("pollen.action.editPoll") : _("pollen.action.createPoll"); @@ -232,10 +658,6 @@ return creator.getUserAccount() != null; } - public boolean isEdit() { - return StringUtils.isNotBlank(getPoll().getTopiaId()); - } - public void prepareFormPage() throws Exception { getPollenSession().removeDynamicDataWithPrefix(IMAGECHOICES_THUMB_PREFIX); @@ -295,6 +717,424 @@ return result; } + protected void validateInformations() { + + // -- Title : required -- // + if (StringUtils.isBlank(poll.getTitle())) { + addInformationsError("poll.title", + _("pollen.error.poll.required.title")); + } + + if (isVoteStarted()) { + + // no validation on choices if vote is started + + } else { + + // -- Choice -- // + if (MapUtils.isEmpty(choices)) { + + // poll must have at least one choice + addInformationsError("poll.choices", + _("pollen.error.poll.required.one.choice")); + } else { + switch (poll.getChoiceType()) { + + case TEXT: + validateTextChoices(); + break; + case DATE: + validateDateChoices(); + break; + case IMAGE: + validateImageChoices(); + break; + } + } + } + } + + protected void validateTextChoices() { + + String choicePrefix = getChoiceFieldPrefix(ChoiceType.TEXT); + + Set<String> choiceNames = Sets.newHashSet(); + + for (Map.Entry<Integer, Choice> entry : choices.entrySet()) { + Integer choiceIndex = entry.getKey(); + Choice choice = entry.getValue(); + String choiceErrorField = choicePrefix + choiceIndex + ".name"; + String choiceName = choice.getName(); + if (StringUtils.isBlank(choiceName)) { + // no name + addInformationsError( + choiceErrorField, + _("pollen.error.poll.choice.name.required")); + continue; + } + if (choiceNames.contains(choiceName)) { + // duplicated names + addInformationsError( + choiceErrorField, + _("pollen.error.poll.choice.already.used.name")); + continue; + } + choiceNames.add(choiceName); + } + } + + protected void validateDateChoices() { + + + String choicePrefix = getChoiceFieldPrefix(ChoiceType.DATE); + + Set<String> choiceNames = Sets.newHashSet(); + + for (Map.Entry<Integer, Choice> entry : choices.entrySet()) { + Integer choiceIndex = entry.getKey(); + PollDateChoice choice = (PollDateChoice) entry.getValue(); + String choiceErrorField = choicePrefix + choiceIndex + ".name"; + String choiceName = choice.getName(); + if (StringUtils.isBlank(choiceName)) { + // no name + addInformationsError( + choiceErrorField, + _("pollen.error.poll.dateChoice.required")); + continue; + } + if (choiceNames.contains(choiceName)) { + // duplicated names + addInformationsError( + choiceErrorField, + _("pollen.error.poll.dateChoice.already.used")); + continue; + } + if (choice.getDate() == null) { + + // format error + addInformationsError( + choiceErrorField, + _("pollen.error.poll.dateChoice.badDateFormat")); + + } + choiceNames.add(choiceName); + } + } + + protected void validateImageChoices() { + + String choicePrefix = getChoiceFieldPrefix(ChoiceType.IMAGE); + + Set<String> choiceNames = Sets.newHashSet(); + + for (Map.Entry<Integer, Choice> entry : choices.entrySet()) { + Integer choiceIndex = entry.getKey(); + Choice choice = entry.getValue(); + String choiceErrorField = choicePrefix + choiceIndex + ".name"; + String choiceName = choice.getName(); + if (StringUtils.isBlank(choiceName)) { + // no name + addInformationsError( + choiceErrorField, + _("pollen.error.poll.imageChoice.upload.required")); + continue; + } + if (choiceNames.contains(choiceName)) { + // duplicated names + addInformationsError( + choiceErrorField, + _("pollen.error.poll.imageChoice.already.used")); + continue; + } + choiceNames.add(choiceName); + } + + } + + protected void validateOptions() { + + if (isVoteStarted()) { + + // no validation on votingLists if vote is started + + } else { + + // -- VotingList -- // + + if (isFreePoll()) { + + // nothing to validate + + } else { + + Set<String> groups = Sets.newHashSet(); + Set<String> voters = Sets.newHashSet(); + Set<String> emails = Sets.newHashSet(); + + for (Map.Entry<Integer, VotingList> entry : votingLists.entrySet()) { + validateVotingList(entry.getKey(), + entry.getValue(), + groups, + voters, + emails); + } + } + } + + String creatorEmail = poll.getCreator().getEmail(); + 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( + "poll.endChoiceDate", + _("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, + VotingList votingList, + Set<String> groups, + Set<String> voters, + Set<String> emails) { + + PollType votingListType = poll.getPollType(); + String fieldNamePrefix = "votingList" + votingListType + "_" + + votingListNumber; + + if (isGroupPoll()) { + + // group poll + + // check there is at least one group + // check no doublon on group names + // check there is at least one voter on each group + // check no doublon on voter names + // check no doublon on voter emails + + // validate votingList name + String votingListName = votingList.getName(); + + if (StringUtils.isEmpty(votingListName)) { + + addOptionsError( + fieldNamePrefix, + _("pollen.error.poll.required.votingList.name")); + } else { + + // check no votingList name doublon + boolean add = groups.add(votingListName); + if (!add) { + + // name doublon + addOptionsError( + fieldNamePrefix, + _("pollen.error.poll.votingList.name.doublon")); + } + } + + // validate votingList weight + + if (votingList.getWeight() == 0) { + + // no weight filled (can be a bad conversion) + addOptionsError( + fieldNamePrefix, + _("pollen.error.poll.votingList.weight.not.valid")); + } + + } + + // check there is at least one voter + + List<PersonToList> personToLists = + votingList.getPollAccountPersonToList(); + + if (CollectionUtils.isEmpty(personToLists)) { + + // no personToList found for unique votingList 0 + addOptionsError(fieldNamePrefix, + _("pollen.error.poll.required.one.personToList")); + } else { + + // check no doublon on voter names + + for (int i = 0; i < personToLists.size(); i++) { + + validatePersonList(i, + fieldNamePrefix, + personToLists.get(i), + voters, + emails); + } + } + } + + protected void validatePersonList(int personToListNumber, + String votingListFieldNamePrefix, + PersonToList personToList, + Set<String> voters, + Set<String> emails) { + + String fieldNamePrefix = votingListFieldNamePrefix + + "PersonToList_" + personToListNumber; + + PollAccount pollAccount = personToList.getPollAccount(); + + // -- validate votingId -- // + + String votingId = pollAccount.getVotingId(); + + if (StringUtils.isEmpty(votingId)) { + + // voter name mandatory + addOptionsError( + fieldNamePrefix, + _("pollen.error.poll.personToList.votingId.required")); + } else { + + boolean add = voters.add(votingId); + if (!add) { + + // voter name already used + addOptionsError( + fieldNamePrefix, + _("pollen.error.poll.personToList.votingId.doublon")); + } + } + + // -- validate email -- // + + String email = pollAccount.getEmail(); + + if (StringUtils.isEmpty(email)) { + + // voter email mandatory + addOptionsError(fieldNamePrefix, + _("pollen.error.email.required")); + } else { + + boolean validEmail = StringUtil.isEmail(email); + if (!validEmail) { + + // not a valid email + addOptionsError(fieldNamePrefix, + _("pollen.error.email.invalid")); + } else { + + boolean add = emails.add(email); + if (!add) { + + // email already used + addOptionsError( + fieldNamePrefix, + _("pollen.error.poll.personToList.email.doublon")); + } + } + } + + // -- validate weight -- // + + if (personToList.getWeight() == 0) { + + // no weight filled (can be a bad conversion) + addOptionsError( + fieldNamePrefix, + _("pollen.error.poll.personToList.weight.not.valid")); + } + + } + + protected boolean validateEndDate(Date begin, Date end) { + return begin != null + && end != null + && end.before(begin); + } + + @Override + public void addFieldError(String fieldName, String errorMessage) { + super.addFieldError(fieldName, errorMessage); + if (log.isDebugEnabled()) { + log.debug("VALIDATION [" + fieldName + "] : " + errorMessage); + } + } + + protected void addInformationsError(String fieldName, String errorMessage) { + addFieldError(fieldName, errorMessage); + informationsError = true; + } + + protected void addOptionsError(String fieldName, String errorMessage) { + addFieldError(fieldName, errorMessage); + optionsError = true; + } + protected void loadChoicesAndvotingLists(Poll poll, Collection<Choice> pollChoices, Collection<VotingList> pollVotinLists, @@ -324,38 +1164,41 @@ for (Choice choice : pollChoices) { PollImageChoice imageChoice = (PollImageChoice) choice; String choiceId = imageChoice.getTopiaId(); - File imageChoiceFile; + File imageChoiceFile = null; PollService service = getPollService(); if (StringUtils.isBlank(choiceId)) { - // new choice, must create the thumb - imageChoiceFile = - new File(imageChoice.getLocation()); + if (!isImageUploadEmpty(imageChoice)) { + // new choice, must create the thumb + imageChoiceFile = + new File(imageChoice.getLocation()); - if (imageChoiceFile.exists()) { + if (imageChoiceFile.exists()) { - service.generateThumbIfNeeded(imageChoiceFile); + service.generateThumbIfNeeded(imageChoiceFile); + } } + } else { // already persisted choice, nothing to do imageChoiceFile = service.getPollChoiceImageFile( poll.getPollId(), choice.getName()); - } - File thumbFile = service.getImageThumbFile( - imageChoiceFile); + if (imageChoiceFile != null) { + File thumbFile = service.getImageThumbFile( + imageChoiceFile); - // keep in session the location of this thumb (do not - // want to expose the full path location in url) - getPollenSession().putDynamicData( - IMAGECHOICES_THUMB_PREFIX + choice.getName(), - thumbFile); + // keep in session the location of this thumb (do not + // want to expose the full path location in url) + getPollenSession().putDynamicData( + IMAGECHOICES_THUMB_PREFIX + choice.getName(), + thumbFile); + } } - break; } } @@ -419,6 +1262,482 @@ getPersontoListCreator(), defaultMaxVoting); } + } + protected boolean isTextChoiceEmpty(Choice textChoice) { + boolean result = + StringUtils.isBlank(textChoice.getName()) && + StringUtils.isBlank(textChoice.getDescription()); + return result; } + + protected boolean isDateChoiceEmpty(PollDateChoice dateChoice) { + boolean result = + StringUtils.isBlank(dateChoice.getName()) && + StringUtils.isBlank(dateChoice.getDescription()); + return result; + } + + protected boolean isImageChoiceEmpty(PollImageChoice imageChoice) { + boolean result = + StringUtils.isBlank(imageChoice.getLocation()) && + StringUtils.isBlank(imageChoice.getDescription()); + return result; + } + + protected boolean isImageUploadEmpty(PollImageChoice imageChoice) { + boolean result = + StringUtils.isBlank(imageChoice.getLocation()); + return result; + } + + protected boolean isPersonToListEmpty(PersonToList personToList) { + PollAccount pollAccount = personToList.getPollAccount(); + boolean result = + StringUtils.isBlank(pollAccount.getVotingId()) && + StringUtils.isBlank(pollAccount.getEmail()); + return result; + } + + protected Map<Integer, Choice> buildTextChoices() { + Map<Integer, Choice> result = Maps.newTreeMap(); + + String fieldPrefix = getChoiceFieldPrefix(ChoiceType.TEXT); + + int maxNumber = 0; + + for (String paramName : parameters.keySet()) { + + Matcher matcher = TEXT_CHOICE_NAME_PATTERN.matcher(paramName); + if (matcher.matches()) { + + // found a text choice name + + String paramValue = getNonEmptyParameterValue(paramName); + + // can keep this none empty text choice name + + Integer choiceNumber = Integer.valueOf(matcher.group(1)); + if (choiceNumber > maxNumber) { + maxNumber = choiceNumber; + } + Choice choice = createChoice(new ChoiceImpl(), + fieldPrefix + choiceNumber, + paramValue); + if (!isTextChoiceEmpty(choice)) { + + // This is not an empty choice keep it + result.put(choiceNumber, choice); + } + } + } + result = reindexMap(result, maxNumber); + + int size = result.size(); + if (log.isInfoEnabled()) { + log.info("nbTextChoices (from request) = " + size); + } + logChoice(result); + return result; + } + + protected Map<Integer, Choice> buildDateChoices() { + Map<Integer, Choice> result = Maps.newTreeMap(); + + String fieldPrefix = getChoiceFieldPrefix(ChoiceType.DATE); + + int maxNumber = 0; + for (String paramName : parameters.keySet()) { + + Matcher matcher = DATE_CHOICE_NAME_PATTERN.matcher(paramName); + if (matcher.matches()) { + + // found a text choice name + + String paramValue = getNonEmptyParameterValue(paramName); + + // can keep this none empty text choice name + + Integer choiceNumber = Integer.valueOf(matcher.group(1)); + if (choiceNumber > maxNumber) { + maxNumber = choiceNumber; + } + String choiceFieldPrefix = fieldPrefix + choiceNumber; + + PollDateChoice choice = createChoice(new PollDateChoice(), + choiceFieldPrefix, + paramValue); + if (StringUtils.isNotBlank(paramValue)) { + Date date = DateConverter.convertFromString(paramValue); + choice.setDate(date); + } + + if (!isDateChoiceEmpty(choice)) { + + // This is not an empty choice keep it + result.put(choiceNumber, choice); + } + } + } + result = reindexMap(result, maxNumber); + + int size = result.size(); + if (log.isInfoEnabled()) { + log.info("nbDateChoices (from request) = " + size); + } + logChoice(result); + return result; + } + + protected Map<Integer, Choice> buildImageChoices() { + Map<Integer, Choice> result = Maps.newTreeMap(); + + String fieldPrefix = getChoiceFieldPrefix(ChoiceType.IMAGE); + + int maxNumber = 0; + + Map<String, String> parametersToSwitch = Maps.newTreeMap(); + + for (String paramName : parameters.keySet()) { + + Matcher matcher = IMAGE_CHOICE_DESCRIPTION_PATTERN.matcher(paramName); + if (matcher.matches()) { + + // found an image choice description + // Note: We can not use as for other choices (text and date) + // the name since there is no name parameter submitted... + // the upload filed will implies a such parameter... + + Integer choiceNumber = Integer.valueOf(matcher.group(1)); + if (choiceNumber > maxNumber) { + maxNumber = choiceNumber; + } + + String choiceFieldPrefix = fieldPrefix + choiceNumber; + + PollImageChoice choice = createChoice(new PollImageChoice(), + choiceFieldPrefix, + null); + String location = getNonEmptyParameterValue( + choiceFieldPrefix + ".newLocation"); + if (StringUtils.isNotBlank(location)) { + + // found a real upload file (not jus the location of an + // already choice uploaded choice + choice.setLocation(location); + + // ok so now use also newName + String paramValue = getNonEmptyParameterValue( + choiceFieldPrefix + ".newName"); + choice.setName(paramValue); + + parametersToSwitch.put(choiceFieldPrefix + ".newLocation", + choiceFieldPrefix + ".location"); + + parametersToSwitch.put(choiceFieldPrefix + ".newName", + choiceFieldPrefix + ".name"); + + } else { + + // try with old location + location = getNonEmptyParameterValue( + choiceFieldPrefix + ".location"); + choice.setLocation(location); + + String paramValue = getNonEmptyParameterValue( + choiceFieldPrefix + ".name"); + choice.setName(paramValue); + } + + if (!isImageChoiceEmpty(choice)) { + + // This is not an empty choice keep it + result.put(choiceNumber, choice); + } + } + } + + // switch new uploaded values + for (Map.Entry<String, String> entry : parametersToSwitch.entrySet()) { + String paramNameSource = entry.getKey(); + String paramNameTarget = entry.getValue(); + String[] valueToSwitch = parameters.remove(paramNameSource); + parameters.put(paramNameTarget, valueToSwitch); + } + result = reindexMap(result, maxNumber); + int size = result.size(); + if (log.isInfoEnabled()) { + log.info("nbImageChoices (from request) = " + size); + } + logChoice(result); + return result; + } + + protected Map<Integer, VotingList> buildVotingLists(PollType pollType) { + Map<Integer, VotingList> result = Maps.newTreeMap(); + + int maxNumber = 0; + + String votingListPrefix = "votingList" + pollType.name(); + + // get all votingList_xxx parameters + Set<String> votingListParameterNames = Sets.filter( + parameters.keySet(), + new StringStartWithPredicate(votingListPrefix)); + + Pattern votingListPattern = Pattern.compile( + "(" + votingListPrefix + ")_(\\d+)\\.name"); + + for (String paramName : votingListParameterNames) { + + Matcher matcher = votingListPattern.matcher(paramName); + + if (matcher.matches()) { + + // found a voting list name + + int votingListNumber = Integer.valueOf(matcher.group(2)); + + buildVotingList(paramName, + votingListPrefix + "_" + votingListNumber, + votingListNumber, + result + ); + maxNumber = Math.max(maxNumber, votingListNumber); + } + } + + result = reindexMap(result, maxNumber); + + int size = result.size(); + if (log.isInfoEnabled()) { + log.info("nbVotingList [" + pollType + "] (from request) = " + size); + } + + // add personToList maps to session (but just now, since votingList + // could have been reindex) + for (Map.Entry<Integer, VotingList> entry : result.entrySet()) { + VotingList votingList = entry.getValue(); + + if (!votingList.isPollAccountPersonToListEmpty()) { + List<PersonToList> personToList = + votingList.getPollAccountPersonToList(); + + Map<Integer, PersonToList> personToListMap = Maps.newTreeMap(); + int index = 0; + for (PersonToList toList : personToList) { + personToListMap.put(index++, toList); + } + } + } + + return result; + } + + private double getDoubleValue(String parameterName) { + String parameterValue = getNonEmptyParameterValue(parameterName); + double result = 0; + if (StringUtils.isNotEmpty(parameterValue)) { + + try { + result = Double.valueOf(parameterValue); + } catch (NumberFormatException e) { + //bad conversion, will be treated later + if (log.isDebugEnabled()) { + log.debug("Bad double conversion from param [" + + parameterName + "] : " + parameterValue); + } + } + } + return result; + } + + private int buildVotingList(String votingListParameterName, + String votingListPrefix, + int votingListNumber, + Map<Integer, VotingList> result) { + + String paramValue = getNonEmptyParameterValue(votingListParameterName); + + VotingList votingList = new VotingListImpl(); + + votingList.setName(paramValue); + + double weight = getDoubleValue(votingListPrefix + ".weight"); + votingList.setWeight(weight); + + String topiaId = getNonEmptyParameterValue(votingListPrefix + ".topiaId"); + votingList.setTopiaId(topiaId); + + result.put(votingListNumber, votingList); + + String personToListPrefix = votingListPrefix + "PersonToList_"; + + // get all personToList parameters + Set<String> votingListParameterNames = Sets.filter( + parameters.keySet(), + new StringStartWithPredicate(personToListPrefix)); + + Pattern personToListNamePattern = Pattern.compile( + personToListPrefix + "(\\d+)\\.votingId"); + + Map<Integer, PersonToList> personToLists = Maps.newTreeMap(); + + int maxPersonToListNumber = 0; + + // let's build personToList list + for (String personToListNameParameter : votingListParameterNames) { + + Matcher matcher = personToListNamePattern.matcher( + personToListNameParameter); + + if (matcher.matches()) { + + int personToListNumber = buildPersonToList( + personToListPrefix, + personToListNameParameter, + matcher, + votingListNumber, + personToLists); + + maxPersonToListNumber = Math.max(maxPersonToListNumber, + personToListNumber); + } + } + + personToLists = reindexMap(personToLists, maxPersonToListNumber); + + for (PersonToList personToList : personToLists.values()) { + votingList.addPollAccountPersonToList(personToList); + } + + return votingListNumber; + } + + private int buildPersonToList(String personToListPrefix, + String paramName, + Matcher personToListMatcher, + int votingListNumber, + Map<Integer, PersonToList> result) { + + int personToListNumber = Integer.valueOf(personToListMatcher.group(1)); + + PersonToList personToList = new PersonToListImpl(); + + PollAccount account = new PollAccountImpl(); + personToList.setPollAccount(account); + + account.setVotingId(getNonEmptyParameterValue(paramName)); + + String prefix = personToListPrefix + personToListNumber; + + double weight = getDoubleValue(prefix + ".weight"); + personToList.setWeight(weight); + + String topiaId = getNonEmptyParameterValue(prefix + ".topiaId"); + personToList.setTopiaId(topiaId); + + String email = getNonEmptyParameterValue(prefix + ".email"); + account.setEmail(email); + + String accountId = getNonEmptyParameterValue(prefix + ".accountId"); + account.setAccountId(accountId); + + if (!isPersonToListEmpty(personToList)) { + + // can keep this not empty personToList + result.put(personToListNumber, personToList); + } + return personToListNumber; + } + + private <C extends Choice> C createChoice(C choice, + String prefix, + String name) { + String description = getNonEmptyParameterValue(prefix + ".description"); + String topiaId = getNonEmptyParameterValue(prefix + ".topiaId"); + choice.setName(name); + choice.setDescription(description); + choice.setTopiaId(topiaId); + return choice; + } + + private void logChoice(Map<Integer, Choice> result) { + for (Map.Entry<Integer, Choice> e : result.entrySet()) { + Integer choiceId = e.getKey(); + Choice choice = e.getValue(); + if (log.isInfoEnabled()) { + log.info("Choice [" + choiceId + "] = " + + choice.getName() + " -- " + + choice.getDescription()); + } + } + } + + protected <T> Map<Integer, T> reindexMap(Map<Integer, T> result, int maxNumber) { + Map<Integer, T> result2; + + if (maxNumber != result.size() - 1) { + + // means there is a hole inside the result (a empty choice was + // submitted) + + // le'ts remove this + List<Integer> numbers = Lists.newArrayList(result.keySet()); + + Collections.sort(numbers); + + result2 = Maps.newTreeMap(); + int i = 0; + for (Integer number : numbers) { + T choice = result.get(number); + result2.put(i++, choice); + } + } else { + result2 = result; + } + return result2; + } + + protected String getNonEmptyParameterValue(String paramName) { + String[] paramValues = parameters.get(paramName); + String result = null; + if (paramValues != null && paramValues.length == 1) { + String paramValue = paramValues[0]; + if (StringUtils.isNotEmpty(paramValue)) { + result = paramValue; + } + } + return result; + } + + private String getChoiceFieldPrefix(ChoiceType choiceType) { + String result = null; + switch (choiceType) { + + case TEXT: + result = "textChoice_"; + break; + case DATE: + result = "dateChoice_"; + break; + case IMAGE: + result = "imageChoice_"; + break; + } + return result; + } + + private static class StringStartWithPredicate implements Predicate<String> { + private final String prefix; + + public StringStartWithPredicate(String prefix) { + this.prefix = prefix; + } + + @Override + public boolean apply(String input) { + return input.startsWith(prefix); + } + } } Modified: trunk/pollen-ui-struts2/src/main/java/org/chorem/pollen/ui/actions/poll/AbstractVoteAction.java =================================================================== --- trunk/pollen-ui-struts2/src/main/java/org/chorem/pollen/ui/actions/poll/AbstractVoteAction.java 2012-06-16 20:33:49 UTC (rev 3493) +++ trunk/pollen-ui-struts2/src/main/java/org/chorem/pollen/ui/actions/poll/AbstractVoteAction.java 2012-06-16 20:36:03 UTC (rev 3494) @@ -120,8 +120,6 @@ */ private String commentAuthor; -// private String voteSizeMessage; - /** * Results of the poll. * @@ -302,8 +300,15 @@ // TODO no pagination for the moment, need to retrieve the correct page depends on current pollAccount votes = getVoteService().getAllVotes(poll); - voteAllowed = !moderate && getVoteService().isVoteAllowed(poll, pollAccount); + voteAllowed = !moderate && getSecurityService().isVoteAllowed(poll, pollAccount); + if (voteAllowed) { + + // can not vote if accountId from the url is the creator one + voteAllowed = !poll.getCreator().getAccountId().equals(getUriId().getAccountId()); + + } + // Current vote if (voteAllowed) { vote = getVoteService().getVoteEditable(poll, pollAccount); @@ -371,7 +376,7 @@ } public boolean isModifAllowed(Vote vote) { - return getVoteService().isUpdateAllowed( + return getSecurityService().isUpdateAllowed( getPoll(), vote.getTopiaId(), getAccountId(), @@ -383,7 +388,7 @@ } public boolean isDeleteCommentAllowed(Comment comment) { - return getPollCommentService().isCanDeleteComment( + return getSecurityService().isCanDeleteComment( comment, getPollAccount(), getPollenUserAccount(), Added: trunk/pollen-ui-struts2/src/main/java/org/chorem/pollen/ui/actions/poll/ClonePoll.java =================================================================== --- trunk/pollen-ui-struts2/src/main/java/org/chorem/pollen/ui/actions/poll/ClonePoll.java (rev 0) +++ trunk/pollen-ui-struts2/src/main/java/org/chorem/pollen/ui/actions/poll/ClonePoll.java 2012-06-16 20:36:03 UTC (rev 3494) @@ -0,0 +1,54 @@ +/* + * #%L + * Pollen :: UI (struts2) + * $Id: SavePoll.java 3467 2012-06-13 15:57:49Z tchemit $ + * $HeadURL: http://svn.chorem.org/svn/pollen/trunk/pollen-ui-struts2/src/main/java/org/c... $ + * %% + * Copyright (C) 2009 - 2012 CodeLutin, Tony Chemit + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * #L% + */ +package org.chorem.pollen.ui.actions.poll; + +import org.chorem.pollen.business.persistence.Poll; + +/** + * Clones a poll. + * + * @author tchemit <chemit@codelutin.com> + * @since 1.4 + */ +public class ClonePoll extends AbstractPollForm { + + private static final long serialVersionUID = 1L; + + @Override + public boolean isClone() { + return true; + } + + @Override + public boolean isEdit() { + return false; + } + + @Override + protected Poll savePoll(Poll poll) { + poll = getPollService().createPoll(poll); + addFlashMessage(_("pollen.information.poll.created", poll.getTitle())); + return poll; + } + +} Copied: trunk/pollen-ui-struts2/src/main/java/org/chorem/pollen/ui/actions/poll/CreatePoll.java (from rev 3486, 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/CreatePoll.java (rev 0) +++ trunk/pollen-ui-struts2/src/main/java/org/chorem/pollen/ui/actions/poll/CreatePoll.java 2012-06-16 20:36:03 UTC (rev 3494) @@ -0,0 +1,54 @@ +/* + * #%L + * Pollen :: UI (struts2) + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2009 - 2012 CodeLutin, Tony Chemit + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * #L% + */ +package org.chorem.pollen.ui.actions.poll; + +import org.chorem.pollen.business.persistence.Poll; + +/** + * Creates a poll. + * + * @author tchemit <chemit@codelutin.com> + * @since 1.4 + */ +public class CreatePoll extends AbstractPollForm { + + private static final long serialVersionUID = 1L; + + @Override + public boolean isClone() { + return false; + } + + @Override + public boolean isEdit() { + return false; + } + + @Override + protected Poll savePoll(Poll poll) { + poll = getPollService().createPoll(poll); + addFlashMessage(_("pollen.information.poll.created", poll.getTitle())); + return poll; + } + +} Added: trunk/pollen-ui-struts2/src/main/java/org/chorem/pollen/ui/actions/poll/EditPoll.java =================================================================== --- trunk/pollen-ui-struts2/src/main/java/org/chorem/pollen/ui/actions/poll/EditPoll.java (rev 0) +++ trunk/pollen-ui-struts2/src/main/java/org/chorem/pollen/ui/actions/poll/EditPoll.java 2012-06-16 20:36:03 UTC (rev 3494) @@ -0,0 +1,58 @@ +/* + * #%L + * Pollen :: UI (struts2) + * $Id: SavePoll.java 3467 2012-06-13 15:57:49Z tchemit $ + * $HeadURL: http://svn.chorem.org/svn/pollen/trunk/pollen-ui-struts2/src/main/java/org/c... $ + * %% + * Copyright (C) 2009 - 2012 CodeLutin, Tony Chemit + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * #L% + */ +package org.chorem.pollen.ui.actions.poll; + +import org.chorem.pollen.business.persistence.Poll; +import org.chorem.pollen.services.exceptions.PollNotFoundException; + +/** + * Edit a poll (load it via {@link #input()}), and save it + * via {@link #execute()}). + * + * @author tchemit <chemit@codelutin.com> + * @since 1.3 + */ +public class EditPoll extends AbstractPollForm { + + private static final long serialVersionUID = 1L; + + @Override + public boolean isClone() { + + // in edit mode never can be a clone + return false; + } + + @Override + public boolean isEdit() { + return true; + } + + @Override + protected Poll savePoll(Poll poll) throws PollNotFoundException { + poll = getPollService().updatePoll(poll); + addFlashMessage(_("pollen.information.poll.updated", poll.getTitle())); + return poll; + } + +} Deleted: 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-16 20:33:49 UTC (rev 3493) +++ trunk/pollen-ui-struts2/src/main/java/org/chorem/pollen/ui/actions/poll/LoadPoll.java 2012-06-16 20:36:03 UTC (rev 3494) @@ -1,163 +0,0 @@ -/* - * #%L - * Pollen :: UI (struts2) - * $Id$ - * $HeadURL$ - * %% - * Copyright (C) 2009 - 2012 CodeLutin, Tony Chemit - * %% - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * #L% - */ -package org.chorem.pollen.ui.actions.poll; - -import org.apache.commons.io.FileUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.chorem.pollen.bean.PollImageChoice; -import org.chorem.pollen.bean.PollUri; -import org.chorem.pollen.business.persistence.Choice; -import org.chorem.pollen.business.persistence.PreventRule; -import org.chorem.pollen.business.persistence.UserAccount; -import org.chorem.pollen.business.persistence.VotingList; -import org.chorem.pollen.common.ChoiceType; -import org.chorem.pollen.services.impl.PollService; -import org.chorem.pollen.services.impl.PreventRuleService; - -import java.io.File; -import java.util.List; - -/** - * Load the poll form for modification (or only read if poll is no more - * editable). - * <p/> - * Created: 04/04/12 - * - * @author fdesbois <desbois@codelutin.com> - * @author tchemit <chemit@codelutin.com> - * @since 1.3 - */ -public class LoadPoll extends AbstractPollForm { - - private static final long serialVersionUID = 1L; - - /** Logger. */ - private static final Log log = LogFactory.getLog(LoadPoll.class); - - private PollUri pollUri; - - private boolean clone; - - public PollUri getUriId() { - return pollUri; - } - - public void setUriId(PollUri pollUri) { - this.pollUri = pollUri; - } - - public void setClone(boolean clone) { - this.clone = clone; - } - - @Override - public String execute() throws Exception { - - prepareFormPage(); - - UserAccount userAccount = getPollenUserAccount(); - String pollUid = pollUri == null ? null : pollUri.getPollId(); - PollService service = getPollService(); - - poll = service.getPollEditable(pollUid, userAccount, clone); - - if (poll.isClosed()) { - addFlashWarning(_("pollen.warning.poll.is.closed.so.read.only")); - } - List<Choice> pollChoices = poll.getChoice(); - - if (clone) { - - if (ChoiceType.IMAGE == poll.getChoiceType()) { - - // recopy images to tmp - - File tmpDir = getConfiguration().getTemporaryDirectory(); - for (Choice choice : pollChoices) { - String choiceName = choice.getName(); - - // image from poll to clone - File imageChoiceFile = service.getPollChoiceImageFile( - pollUid, - choiceName - ); - - // new image - File newImageChoiceFile = File.createTempFile( - choiceName, null, tmpDir); - - if (log.isInfoEnabled()) { - log.info("Copy image from " + imageChoiceFile + - " to " + newImageChoiceFile); - } - FileUtils.copyFile(imageChoiceFile, - newImageChoiceFile); - - ((PollImageChoice) choice).setLocation( - newImageChoiceFile.getAbsolutePath()); - } - } - } - - List<VotingList> pollVotingLists = poll.getVotingList(); - - loadChoicesAndvotingLists(poll, - pollChoices, - pollVotingLists, - !isVoteStarted()); - - 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( - PreventRuleService.SCOPE_VOTE); - if (notification != null) { - setNotification(true); - } - - if (isVoteStarted()) { - addFlashMessage(_("pollen.information.poll.form.voteStarted")); - } - - return SUCCESS; - } - - -} Deleted: 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-16 20:33:49 UTC (rev 3493) +++ trunk/pollen-ui-struts2/src/main/java/org/chorem/pollen/ui/actions/poll/SavePoll.java 2012-06-16 20:36:03 UTC (rev 3494) @@ -1,1099 +0,0 @@ -/* - * #%L - * Pollen :: UI (struts2) - * $Id$ - * $HeadURL$ - * %% - * Copyright (C) 2009 - 2012 CodeLutin, Tony Chemit - * %% - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * #L% - */ -package org.chorem.pollen.ui.actions.poll; - -import com.google.common.base.Predicate; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; -import com.opensymphony.xwork2.Preparable; -import com.opensymphony.xwork2.interceptor.annotations.InputConfig; -import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.collections.MapUtils; -import org.apache.commons.io.FileUtils; -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.struts2.interceptor.ParameterAware; -import org.chorem.pollen.bean.ChoiceHelper; -import org.chorem.pollen.bean.PollDateChoice; -import org.chorem.pollen.bean.PollImageChoice; -import org.chorem.pollen.bean.PollUri; -import org.chorem.pollen.business.persistence.Choice; -import org.chorem.pollen.business.persistence.ChoiceImpl; -import org.chorem.pollen.business.persistence.PersonToList; -import org.chorem.pollen.business.persistence.PersonToListImpl; -import org.chorem.pollen.business.persistence.PollAccount; -import org.chorem.pollen.business.persistence.PollAccountImpl; -import org.chorem.pollen.business.persistence.PreventRule; -import org.chorem.pollen.business.persistence.UserAccount; -import org.chorem.pollen.business.persistence.VotingList; -import org.chorem.pollen.business.persistence.VotingListImpl; -import org.chorem.pollen.common.ChoiceType; -import org.chorem.pollen.common.PollType; -import org.chorem.pollen.services.impl.PreventRuleService; -import org.chorem.pollen.ui.actions.FileUploadAware; -import org.chorem.pollen.ui.converters.DateConverter; -import org.nuiton.util.StringUtil; - -import java.io.File; -import java.util.Collection; -import java.util.Collections; -import java.util.Date; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Saves the incoming poll, could be a new poll or just an update. - * - * @author tchemit <chemit@codelutin.com> - * @since 1.3 - */ -public class SavePoll extends AbstractPollForm implements Preparable, ParameterAware, FileUploadAware { - - private static final long serialVersionUID = 1L; - - /** Logger. */ - private static final Log log = LogFactory.getLog(SavePoll.class); - - private static final Pattern TEXT_CHOICE_NAME_PATTERN = - Pattern.compile("textChoice_(\\d+)\\.name"); - - private static final Pattern DATE_CHOICE_NAME_PATTERN = - Pattern.compile("dateChoice_(\\d+)\\.name"); - - private static final Pattern IMAGE_CHOICE_NAME_PATTERN = - Pattern.compile("imageChoice_(\\d+)\\.name"); - - /** - * Flag when there is some errors on the information panel. - * - * @since 1.3 - */ - protected boolean informationsError; - - /** - * Flag when there is some errors on the options panel. - * - * @since 1.3 - */ - private boolean optionsError; - - /** - * All the parameters send by request used to build back choices of the - * poll. - * - * @since 1.3 - */ - protected final Map<String, String[]> parameters = Maps.newTreeMap(); - - /** - * Indexed choices retreive from parameters for the choiceType selected in - * form. (Other choices are lost). - * - * @since 1.3 - */ - private Map<Integer, Choice> choices; - - /** - * Indexed voting lists retreive from parameters for the pollType selected - * in form. (Other voting lists are lost). - * - * @since 1.3 - */ - private Map<Integer, VotingList> votingLists; - - @Override - public void prepare() throws Exception { - - prepareFormPage(); - - String pollUid = getNonEmptyParameterValue("poll.pollId"); - String userId = getNonEmptyParameterValue("userId"); - if (StringUtils.isBlank(userId)) { - - // try to take the one from current user - UserAccount userAccount = getPollenUserAccount(); - if (userAccount != null) { - userId = userAccount.getTopiaId(); - } - } - UserAccount userAccount = null; - if (StringUtils.isNotBlank(userId)) { - // load use account to use - userAccount = getPollService().getEntityById( - UserAccount.class, userId); - } - - // get a copy (or a fresh new poll) - poll = getPollService().getPollEditable(pollUid, userAccount, false); - - // If vote is started, prepare choices and votingLists is useless - // because they can't be updated. - if (!isVoteStarted()) { - - // Retrieve choiceType from parameters, the poll object will be updated after prepare - String choiceTypeParam = getNonEmptyParameterValue("poll.choiceType"); - ChoiceType pollChoiceType = ChoiceType.valueOf(choiceTypeParam); - poll.setChoiceType(pollChoiceType); - - // build poll choices - - switch (pollChoiceType) { - - case TEXT: - choices = buildTextChoices(); - break; - case DATE: - choices = buildDateChoices(); - break; - case IMAGE: - choices = buildImageChoices(); - break; - } - PollType pollType; - String pollTypeParam = getNonEmptyParameterValue("poll.pollType"); - pollType = PollType.valueOf(pollTypeParam); - switch (pollType) { - - case FREE: - - // empty voting list - votingLists = Maps.newTreeMap(); - break; - case RESTRICTED: - - // restricted voting list - votingLists = buildVotingLists(pollType); - break; - case GROUP: - - // group voting lists - votingLists = buildVotingLists(pollType); - break; - } - } - } - - public PollUri getUriId() { - return PollUri.newPollUri(poll.getAdminId()); - } - - @Override - public String input() throws Exception { - - Collection<Choice> pollChoices = - isVoteStarted() ? poll.getChoice() : choices.values(); - Collection<VotingList> pollVotingLists = - isVoteStarted() ? poll.getVotingList() : votingLists.values(); - - if (ChoiceType.IMAGE == poll.getChoiceType()) { - - // recopy images for new choices, the one uploaded will be - // destroyed, by the upload interceptor - - File tmpDir = getConfiguration().getTemporaryDirectory(); - - for (Choice choice : pollChoices) { - - String choiceId = choice.getTopiaId(); - - if (StringUtils.isBlank(choiceId)) { - - PollImageChoice imageChoice = (PollImageChoice) choice; - - File uploadedImage = new File(imageChoice.getLocation()); - File copyImage = File.createTempFile( - uploadedImage.getName(), null, tmpDir); - - if (log.isInfoEnabled()) { - log.info("Copy image from " + uploadedImage + - " to " + copyImage); - } - FileUtils.copyFile(uploadedImage, copyImage); - - imageChoice.setLocation(copyImage.getAbsolutePath()); - } - } - } - - loadChoicesAndvotingLists(poll, pollChoices, pollVotingLists, true); - return INPUT; - } - - - @Override - public void validate() { - - validateInformations(); - - validateOptions(); - } - - @Override - @InputConfig(methodName = "input") - public String execute() throws Exception { - - // Save choices and votingLists only if vote is not started - if (!isVoteStarted()) { - //TODO-tchemit comment me 2012-06-04 A merge would be nicer but more complex to code - // Clear previous collections to save those from the form - poll.clearChoice(); - poll.clearVotingList(); - for (Integer index : choices.keySet()) { - Choice choice = choices.get(index); - poll.addChoice(choice); - } - - if (!isFreePoll()) { - - for (Integer index : votingLists.keySet()) { - VotingList votingList = votingLists.get(index); - poll.addVotingList(votingList); - } - } - } - - if (isLimitChoice()) { - - // push back filled value - poll.setMaxChoiceNb(getMaxChoices()); - } else { - // reset value - poll.setMaxChoiceNb(0); - } - - if (!poll.isPublicResults()) { - - // force to not have continous results - poll.setContinuousResults(false); - } - - if (poll.isAnonymous()) { - - // force to not have choice to vote anonymously - poll.setAnonymousVoteAllowed(false); - } - - //TODO-tchemit comment me 2012-06-04 A merge would be nicer but more complex to code - poll.clearPreventRule(); - - PreventRuleService preventRuleService = getPreventRuleService(); - if (isNotification()) { - - // add a notification rule - - PreventRule rule = preventRuleService.createAddVotePreventRule(); - poll.addPreventRule(rule); - } - - if (isReminder()) { - - // add a reminder rule - - PreventRule rule = preventRuleService.createRemindPreventRule( - getReminderHourCountdown() - ); - - poll.addPreventRule(rule); - } - - if (isEdit()) { - getPollService().updatePoll(poll); - addFlashMessage( - _("pollen.information.poll.updated", poll.getTitle())); - - } else { - poll = getPollService().createPoll(poll); - addFlashMessage( - _("pollen.information.poll.created", poll.getTitle())); - } - - // remove all stuff from session - getPollenSession().clearDynamicData(); - - return SUCCESS; - } - - @Override - public void addFile(int index, File file) { - parameters.put("imageChoice_" + index + ".location", - new String[]{file.getAbsolutePath()}); - } - - @Override - public void addFileContentType(int index, String contentType) { - // not used here - } - - @Override - public void addFileName(int index, String fileName) { - parameters.put("imageChoice_" + index + ".name", new String[]{fileName}); - } - - @Override - public void setParameters(Map<String, String[]> parameters) { - this.parameters.putAll(parameters); - } - - @Override - public boolean isInformationsError() { - return informationsError; - } - - @Override - public boolean isOptionsError() { - return optionsError; - } - - @Override - public int getSelectedTab() { - int result; - if (isInformationsError()) { - result = 0; - } else { - if (isOptionsError()) { - result = 1; - } else { - result = 0; - } - } - return result; - } - - protected void validateInformations() { - - // -- Title : required -- // - if (StringUtils.isBlank(poll.getTitle())) { - addInformationsError("poll.title", - _("pollen.error.poll.required.title")); - } - - if (isVoteStarted()) { - - // no validation on choices if vote is started - - } else { - - // -- Choice -- // - - if (MapUtils.isEmpty(choices)) { - - // poll must have at least one choice - addInformationsError("poll.choices", - _("pollen.error.poll.required.one.choice")); - } else { - - // get all names from choices - Set<String> choiceNames = - Sets.newHashSet(ChoiceHelper.toNames(choices.values())); - - if (choices.size() > choiceNames.size()) { - - // theire is some duplicated names - addInformationsError( - "poll.choices", - _("pollen.error.poll.detected.duplicate.choice.name")); - } - } - } - } - - protected void validateOptions() { - - if (isVoteStarted()) { - - // no validation on votingLists if vote is started - - } else { - - // -- VotingList -- // - - if (isFreePoll()) { - - // nothing to validate - - } else { - - Set<String> groups = Sets.newHashSet(); - Set<String> voters = Sets.newHashSet(); - Set<String> emails = Sets.newHashSet(); - - for (Map.Entry<Integer, VotingList> entry : votingLists.entrySet()) { - validateVotingList(entry.getKey(), - entry.getValue(), - groups, - voters, - emails); - } - } - } - - String creatorEmail = poll.getCreator().getEmail(); - 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( - "poll.endChoiceDate", - _("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, - VotingList votingList, - Set<String> groups, - Set<String> voters, - Set<String> emails) { - - PollType votingListType = poll.getPollType(); - String fieldNamePrefix = "votingList" + votingListType + "_" + - votingListNumber; - - if (isGroupPoll()) { - - // group poll - - // check there is at least one group - // check no doublon on group names - // check there is at least one voter on each group - // check no doublon on voter names - // check no doublon on voter emails - - { // validate votingList name - String votingListName = votingList.getName(); - - if (StringUtils.isEmpty(votingListName)) { - - addOptionsError( - fieldNamePrefix, - _("pollen.error.poll.required.votingList.name")); - } else { - - // check no votingList name doublon - boolean add = groups.add(votingListName); - if (!add) { - - // name doublon - addOptionsError( - fieldNamePrefix, - _("pollen.error.poll.votingList.name.doublon")); - } - - } - } - - { // validate votingList weight - - if (votingList.getWeight() == 0) { - - // no weight filled (can be a bad conversion) - addOptionsError( - fieldNamePrefix, - _("pollen.error.poll.votingList.weight.not.valid")); - } - } - } - - // check there is at least one voter - - List<PersonToList> personToLists = - votingList.getPollAccountPersonToList(); - - if (CollectionUtils.isEmpty(personToLists)) { - - // no personToList found for unique votingList 0 - addOptionsError(fieldNamePrefix, - _("pollen.error.poll.required.one.personToList")); - } else { - - // check no doublon on voter names - // check no doublon on voter emails - - for (int i = 0; i < personToLists.size(); i++) { - - validatePersonList(i, - fieldNamePrefix, - personToLists.get(i), - voters, - emails); - } - } - } - - protected void validatePersonList(int personToListNumber, - String votingListFieldNamePrefix, - PersonToList personToList, - Set<String> voters, - Set<String> emails) { - - String fieldNamePrefix = votingListFieldNamePrefix + - "PersonToList_" + personToListNumber; - - PollAccount pollAccount = personToList.getPollAccount(); - - { // validate votingId - - String votingId = pollAccount.getVotingId(); - // check voter is not doublon - boolean add = voters.add(votingId); - if (!add) { - - // voter doublon - addOptionsError( - fieldNamePrefix, - _("pollen.error.poll.personToList.votingId.doublon")); - } - } - { // validate email - String email = pollAccount.getEmail(); - - if (StringUtils.isEmpty(email)) { - addOptionsError( - fieldNamePrefix, - _("pollen.error.email.required")); - } else { - - - boolean validEmail = StringUtil.isEmail(email); - if (!validEmail) { - - // not a valid email - addOptionsError( - fieldNamePrefix, - _("pollen.error.email.invalid")); - } else { - - // check email not doublon - boolean add = emails.add(email); - if (!add) { - - // email doublon - addOptionsError( - fieldNamePrefix, - _("pollen.error.poll.personToList.email.doublon")); - } - } - } - } - { // validate weight - if (personToList.getWeight() == 0) { - - // no weight filled (can be a bad conversion) - addOptionsError( - fieldNamePrefix, - _("pollen.error.poll.personToList.weight.not.valid")); - } - } - } - - protected boolean validateEndDate(Date begin, Date end) { - return begin != null - && end != null - && end.before(begin); - } - - @Override - public void addFieldError(String fieldName, String errorMessage) { - super.addFieldError(fieldName, errorMessage); - if (log.isDebugEnabled()) { - log.debug("VALIDATION [" + fieldName + "] : " + errorMessage); - } - } - - protected void addInformationsError(String fieldName, String errorMessage) { - addFieldError(fieldName, errorMessage); - informationsError = true; - } - - protected void addOptionsError(String fieldName, String errorMessage) { - addFieldError(fieldName, errorMessage); - optionsError = true; - } - - protected Map<Integer, Choice> buildTextChoices() { - Map<Integer, Choice> result = Maps.newTreeMap(); - - int maxNumber = 0; - - for (String paramName : parameters.keySet()) { - - Matcher matcher = TEXT_CHOICE_NAME_PATTERN.matcher(paramName); - if (matcher.matches()) { - - // found a text choice name - - String paramValue = getNonEmptyParameterValue(paramName); - if (paramValue != null) { - - // can keep this none empty text choice name - - Integer choiceNumber = Integer.valueOf(matcher.group(1)); - if (choiceNumber > maxNumber) { - maxNumber = choiceNumber; - } - Choice choice = new ChoiceImpl(); - createChoice(choice, "textChoice_" + choiceNumber, - paramValue); - result.put(choiceNumber, choice); - } - } - } - result = reindexMap(result, maxNumber); - - int size = result.size(); - if (log.isInfoEnabled()) { - log.info("nbTextChoices (from request) = " + size); - } - logChoice(result); - return result; - } - - protected Map<Integer, Choice> buildDateChoices() { - Map<Integer, Choice> result = Maps.newTreeMap(); - - int maxNumber = 0; - for (String paramName : parameters.keySet()) { - - Matcher matcher = DATE_CHOICE_NAME_PATTERN.matcher(paramName); - if (matcher.matches()) { - - // found a text choice name - - String paramValue = getNonEmptyParameterValue(paramName); - if (paramValue != null) { - - // can keep this none empty text choice name - - Integer choiceNumber = Integer.valueOf(matcher.group(1)); - if (choiceNumber > maxNumber) { - maxNumber = choiceNumber; - } - PollDateChoice choice = new PollDateChoice(); - createDateChoice(choice, - "dateChoice_" + choiceNumber, - paramValue); - result.put(choiceNumber, choice); - } - } - } - result = reindexMap(result, maxNumber); - - int size = result.size(); - if (log.isInfoEnabled()) { - log.info("nbDateChoices (from request) = " + size); - } - logChoice(result); - return result; - } - - protected Map<Integer, Choice> buildImageChoices() { - Map<Integer, Choice> result = Maps.newTreeMap(); - - int maxNumber = 0; - for (String paramName : parameters.keySet()) { - - Matcher matcher = IMAGE_CHOICE_NAME_PATTERN.matcher(paramName); - if (matcher.matches()) { - - // found an image choice name - - String paramValue = getNonEmptyParameterValue(paramName); - if (paramValue != null) { - - // can keep this none empty text choice name - - Integer choiceNumber = Integer.valueOf(matcher.group(1)); - if (choiceNumber > maxNumber) { - maxNumber = choiceNumber; - } - PollImageChoice choice = new PollImageChoice(); - createImageChoice(choice, - "imageChoice_" + choiceNumber, - paramValue); - - result.put(choiceNumber, choice); - } - } - } - result = reindexMap(result, maxNumber); - int size = result.size(); - if (log.isInfoEnabled()) { - log.info("nbImageChoices (from request) = " + size); - } - logChoice(result); - return result; - } - - protected Map<Integer, VotingList> buildVotingLists(PollType pollType) { - Map<Integer, VotingList> result = Maps.newTreeMap(); - - int maxNumber = 0; - - String votingListPrefix = "votingList" + pollType.name(); - - // get all votingList_ parameters - Set<String> votingListParameterNames = Sets.filter( - parameters.keySet(), - new StringStartWithPredicate(votingListPrefix)); - - Pattern votingListPattern = Pattern.compile( - "(" + votingListPrefix + ")_(\\d+)\\.name"); - - for (String paramName : votingListParameterNames) { - - Matcher matcher = votingListPattern.matcher(paramName); - - if (matcher.matches()) { - - // found a voting list name - - int votingListNumber = Integer.valueOf(matcher.group(2)); - - buildVotingList(paramName, - votingListPrefix+ "_" + votingListNumber, - votingListNumber, - result - ); - maxNumber = Math.max(maxNumber, votingListNumber); - } - } - - result = reindexMap(result, maxNumber); - - int size = result.size(); - if (log.isInfoEnabled()) { - log.info("nbVotingList [" + pollType + "] (from request) = " + size); - } - - // add personToList maps to session (but just now, since votingList - // could have been reindex) - for (Map.Entry<Integer, VotingList> entry : result.entrySet()) { - VotingList votingList = entry.getValue(); - - if (!votingList.isPollAccountPersonToListEmpty()) { - List<PersonToList> personToList = - votingList.getPollAccountPersonToList(); - - Map<Integer, PersonToList> personToListMap = Maps.newTreeMap(); - int index = 0; - for (PersonToList toList : personToList) { - personToListMap.put(index++, toList); - } - } - } - - return result; - } - - private double getDoubleValue(String parameterName) { - String parameterValue = getNonEmptyParameterValue(parameterName); - double result = 0; - if (StringUtils.isNotEmpty(parameterValue)) { - - try { - result = Double.valueOf(parameterValue); - } catch (NumberFormatException e) { - //bad conversion, will be treated later - if (log.isDebugEnabled()) { - log.debug("Bad double conversion from param [" + - parameterName + "] : " + parameterValue); - } - } - } - return result; - } - - private int buildVotingList(String votingListParameterName, - String votingListPrefix, - int votingListNumber, - Map<Integer, VotingList> result) { - - String paramValue = getNonEmptyParameterValue(votingListParameterName); - - VotingList votingList = new VotingListImpl(); - - votingList.setName(paramValue); - - double weight = getDoubleValue(votingListPrefix + ".weight"); - votingList.setWeight(weight); - - String topiaId = getNonEmptyParameterValue(votingListPrefix + ".topiaId"); - votingList.setTopiaId(topiaId); - - result.put(votingListNumber, votingList); - - String personToListPrefix = votingListPrefix + "PersonToList_"; - - // get all personToList parameters - Set<String> votingListParameterNames = Sets.filter( - parameters.keySet(), - new StringStartWithPredicate(personToListPrefix)); - - Pattern personToListNamePattern = Pattern.compile( - personToListPrefix + "(\\d+)\\.votingId"); - - Map<Integer, PersonToList> personToLists = Maps.newTreeMap(); - - int maxPersonToListNumber = 0; - - // let's build personToList list - for (String personToListNameParameter : votingListParameterNames) { - - Matcher matcher = personToListNamePattern.matcher( - personToListNameParameter); - - if (matcher.matches()) { - - int personToListNumber = buildPersonToList( - personToListPrefix, - personToListNameParameter, - matcher, - votingListNumber, - personToLists); - - maxPersonToListNumber = Math.max(maxPersonToListNumber, - personToListNumber); - } - } - - personToLists = reindexMap(personToLists, maxPersonToListNumber); - - for (PersonToList personToList : personToLists.values()) { - votingList.addPollAccountPersonToList(personToList); - } - - return votingListNumber; - } - - private int buildPersonToList(String personToListPrefix, - String paramName, - Matcher personToListMatcher, - int votingListNumber, - Map<Integer, PersonToList> result) { - - String paramValue = getNonEmptyParameterValue(paramName); - - int personToListNumber = 0; - - if (paramValue != null) { - - // found a PersonToList none empty name, keep it - - personToListNumber = Integer.valueOf(personToListMatcher.group(1)); - - PersonToList personToList = new PersonToListImpl(); - - PollAccount account = new PollAccountImpl(); - personToList.setPollAccount(account); - - account.setVotingId(paramValue); - - String prefix = personToListPrefix + personToListNumber; - - double weight = getDoubleValue(prefix + ".weight"); - personToList.setWeight(weight); - - String topiaId = getNonEmptyParameterValue(prefix + ".topiaId"); - personToList.setTopiaId(topiaId); - - String email = getNonEmptyParameterValue(prefix + ".email"); - account.setEmail(email); - - String accountId = getNonEmptyParameterValue(prefix + ".accountId"); - account.setAccountId(accountId); - - result.put(personToListNumber, personToList); - } - return personToListNumber; - } - - private Choice createImageChoice(PollImageChoice choice, - String prefix, - String name) { - createChoice(choice, prefix, name); - String locationName = prefix + ".location"; - String location = getNonEmptyParameterValue(locationName); - choice.setLocation(location); - if (log.isInfoEnabled()) { - log.info("image location [" + name + "] =" + location); - } - return choice; - } - - private Choice createDateChoice(PollDateChoice choice, - String prefix, - String name) { - createChoice(choice, prefix, name); - if (StringUtils.isNotEmpty(name)) { - Date date = DateConverter.convertFromString(name); - if (date == null) { - addInformationsError(prefix, _("pollen.error.date.format")); - } - choice.setDate(date); - } - return choice; - } - - private Choice createChoice(Choice choice, String prefix, String name) { - String descriptionName = prefix + ".description"; - String topiaIdName = prefix + ".topiaId"; - String description = getNonEmptyParameterValue(descriptionName); - String topiaId = getNonEmptyParameterValue(topiaIdName); - choice.setName(name); - choice.setDescription(description); - choice.setTopiaId(topiaId); - return choice; - } - - private void logChoice(Map<Integer, Choice> result) { - for (Map.Entry<Integer, Choice> e : result.entrySet()) { - Integer choiceId = e.getKey(); - Choice choice = e.getValue(); - if (log.isInfoEnabled()) { - log.info("Choice [" + choiceId + "] = " + - choice.getName() + " -- " + - choice.getDescription()); - } - } - } - - protected <T> Map<Integer, T> reindexMap(Map<Integer, T> result, int maxNumber) { - Map<Integer, T> result2; - - if (maxNumber != result.size() - 1) { - - // means there is a hole inside the result (a empty choice was - // submitted) - - // le'ts remove this - List<Integer> numbers = Lists.newArrayList(result.keySet()); - - Collections.sort(numbers); - - result2 = Maps.newTreeMap(); - int i = 0; - for (Integer number : numbers) { - T choice = result.get(number); - result2.put(i++, choice); - } - } else { - result2 = result; - } - return result2; - } - - protected String getNonEmptyParameterValue(String paramName) { - String[] paramValues = parameters.get(paramName); - String result = null; - if (paramValues != null && paramValues.length == 1) { - String paramValue = paramValues[0]; - if (StringUtils.isNotEmpty(paramValue)) { - result = paramValue; - } - } - return result; - } - - private static class StringStartWithPredicate implements Predicate<String> { - private final String prefix; - - public StringStartWithPredicate(String prefix) { - this.prefix = prefix; - } - - @Override - public boolean apply(String input) { - return input.startsWith(prefix); - } - } -} Modified: trunk/pollen-ui-struts2/src/main/java/org/chorem/pollen/ui/actions/poll/SummaryPoll.java =================================================================== --- trunk/pollen-ui-struts2/src/main/java/org/chorem/pollen/ui/actions/poll/SummaryPoll.java 2012-06-16 20:33:49 UTC (rev 3493) +++ trunk/pollen-ui-struts2/src/main/java/org/chorem/pollen/ui/actions/poll/SummaryPoll.java 2012-06-16 20:36:03 UTC (rev 3494) @@ -25,6 +25,7 @@ import com.google.common.base.Preconditions; import org.chorem.pollen.business.persistence.Poll; import org.chorem.pollen.common.PollType; +import org.chorem.pollen.services.impl.SecurityService; import org.chorem.pollen.ui.actions.PageSkin; /** @@ -82,7 +83,9 @@ } public boolean isCanShowResult() { - return poll.isPublicResults(); + String errorMessage = getSecurityService().isCanShowResult( + poll, SecurityService.AccountIdRole.CREATOR); + return errorMessage == null; } public boolean isCanVote() { Modified: trunk/pollen-ui-struts2/src/main/java/org/chorem/pollen/ui/actions/poll/VoteForPoll.java =================================================================== --- trunk/pollen-ui-struts2/src/main/java/org/chorem/pollen/ui/actions/poll/VoteForPoll.java 2012-06-16 20:33:49 UTC (rev 3493) +++ trunk/pollen-ui-struts2/src/main/java/org/chorem/pollen/ui/actions/poll/VoteForPoll.java 2012-06-16 20:36:03 UTC (rev 3494) @@ -61,7 +61,11 @@ } else if (isPollFinished()) { addFlashMessage(_("pollen.information.pollFinished")); } else if (isCreatorUser()) { - addFlashWarning(_("pollen.information.vote.creatorUser")); + if (getUriId().isAccountIdNotBlank()) { + + // account Id setted in url, so should not be abel to vote + addFlashWarning(_("pollen.information.vote.creatorUser")); + } } if (isPollChoiceRunning()) { addFlashMessage(_("pollen.information.pollChoiceRunning")); Modified: trunk/pollen-ui-struts2/src/main/java/org/chorem/pollen/ui/security/PollResultAccessRequired.java =================================================================== --- trunk/pollen-ui-struts2/src/main/java/org/chorem/pollen/ui/security/PollResultAccessRequired.java 2012-06-16 20:33:49 UTC (rev 3493) +++ trunk/pollen-ui-struts2/src/main/java/org/chorem/pollen/ui/security/PollResultAccessRequired.java 2012-06-16 20:36:03 UTC (rev 3494) @@ -24,7 +24,6 @@ import org.chorem.pollen.bean.PollUri; import org.chorem.pollen.business.persistence.Poll; -import org.chorem.pollen.common.PollType; import org.chorem.pollen.services.PollenServiceContext; import org.chorem.pollen.services.impl.PollService; import org.chorem.pollen.services.impl.SecurityService; @@ -114,49 +113,18 @@ // check now poll results can be displayed - boolean publicResults = poll.isPublicResults(); - boolean continuousResults = poll.isContinuousResults(); + String errorMessage = securityService.isCanShowResult( + poll, accountIdRole); - if (!continuousResults && !poll.isClosed()) { + if (errorMessage != null) { - // results are not continuous and poll is not closed + // can not show results isAccessAllowed = false; - registerError( - request, - n_("pollen.security.error.poll.not.closed.and.results.not.continuous")); + registerError(request, errorMessage); } - - if (isAccessAllowed) { - - if (!publicResults && - accountIdRole != SecurityService.AccountIdRole.CREATOR) { - - // poll results are private, only poll admin can see results - isAccessAllowed = false; - registerError( - request, - n_("pollen.security.error.poll.result.private.and.access.not.granted")); - } - } - - if (isAccessAllowed) { - - boolean pollIsFree = PollType.FREE == poll.getPollType(); - - if (publicResults && - !pollIsFree && - !SecurityService.NONE_FREE_ACCOUNT_ID_ROLES.contains(accountIdRole)) { - - // on none free poll, only creator or restricted user can have it - isAccessAllowed = false; - registerError( - request, - n_("pollen.security.error.poll.not.free.and.access.not.granted")); - } - } } - return isAccessAllowed; } + } \ No newline at end of file Modified: trunk/pollen-ui-struts2/src/main/resources/config/struts-poll.xml =================================================================== --- trunk/pollen-ui-struts2/src/main/resources/config/struts-poll.xml 2012-06-16 20:33:49 UTC (rev 3493) +++ trunk/pollen-ui-struts2/src/main/resources/config/struts-poll.xml 2012-06-16 20:36:03 UTC (rev 3494) @@ -40,32 +40,27 @@ </result-types> <!-- create poll --> - <action name="create" class="org.chorem.pollen.ui.actions.poll.LoadPoll"> - <result>/WEB-INF/jsp/poll/create.jsp</result> + <action name="create" class="org.chorem.pollen.ui.actions.poll.CreatePoll"> + <result name="input">/WEB-INF/jsp/poll/create.jsp</result> + <result type="pollenRedirectAction"> + <param name="namespace">/poll</param> + <param name="actionName">summary/${uriId}</param> + </result> </action> - <!-- display * --> - <action name="display*" - class="org.chorem.pollen.ui.actions.poll.Display{1}"> - <result>/WEB-INF/jsp/poll/display{1}.jsp</result> - </action> - <!-- edit poll --> - <action name="modification/*" - class="org.chorem.pollen.ui.actions.poll.LoadPoll"> + <action name="edit/*" class="org.chorem.pollen.ui.actions.poll.EditPoll"> <param name="uriId">{1}</param> - <result>/WEB-INF/jsp/poll/create.jsp</result> + <result name="input">/WEB-INF/jsp/poll/create.jsp</result> + <result type="pollenRedirectAction"> + <param name="namespace">/poll</param> + <param name="actionName">summary/${uriId}</param> + </result> </action> <!-- clone poll --> - <action name="clone/*" class="org.chorem.pollen.ui.actions.poll.LoadPoll"> + <action name="clone/*" class="org.chorem.pollen.ui.actions.poll.ClonePoll"> <param name="uriId">{1}</param> - <param name="clone">true</param> - <result>/WEB-INF/jsp/poll/create.jsp</result> - </action> - - <!-- save poll --> - <action name="save" class="org.chorem.pollen.ui.actions.poll.SavePoll"> <result name="input">/WEB-INF/jsp/poll/create.jsp</result> <result type="pollenRedirectAction"> <param name="namespace">/poll</param> @@ -73,6 +68,12 @@ </result> </action> + <!-- display * --> + <action name="display*" + class="org.chorem.pollen.ui.actions.poll.Display{1}"> + <result>/WEB-INF/jsp/poll/display{1}.jsp</result> + </action> + <!-- resume poll --> <action name="summary/*" method="execute" class="org.chorem.pollen.ui.actions.poll.SummaryPoll"> @@ -108,13 +109,6 @@ <result type="redirect2"/> </action> - <!-- display result link --> - <action name="resultLink/*" - class="org.chorem.pollen.ui.actions.poll.ResultLink"> - <param name="uriId">{1}</param> - <result>/WEB-INF/jsp/poll/resultLink.jsp</result> - </action> - <!-- confirm delete poll --> <action name="confirmDeletePoll/*" class="org.chorem.pollen.ui.actions.poll.ConfirmPollAction"> 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-16 20:33:49 UTC (rev 3493) +++ trunk/pollen-ui-struts2/src/main/resources/i18n/pollen-ui-struts2_en_GB.properties 2012-06-16 20:36:03 UTC (rev 3494) @@ -172,17 +172,25 @@ pollen.error.password.required=Your must provide a password pollen.error.password2.required=You must repeat your password for confirmation pollen.error.passwords.not.equals=The two password are not the same +pollen.error.poll.choice.already.used.name=Choice already used. +pollen.error.poll.choice.name.required=Choice name is mandatory. +pollen.error.poll.dateChoice.already.used=Date already used. +pollen.error.poll.dateChoice.badDateFormat=Invalid date format, required format is MM/dd/yyyy [hh\:mm] (example 12/31/2000 12\:59) +pollen.error.poll.dateChoice.required=Date is required. 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.imageChoice.already.used=Image choice name already used. +pollen.error.poll.imageChoice.upload.required=Upload an image is mandatory. 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.email.doublon=Email already used. +pollen.error.poll.personToList.votingId.doublon=This voter's name is already used. +pollen.error.poll.personToList.votingId.required=Voter's name mandatory. 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. 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-16 20:33:49 UTC (rev 3493) +++ trunk/pollen-ui-struts2/src/main/resources/i18n/pollen-ui-struts2_fr_FR.properties 2012-06-16 20:36:03 UTC (rev 3494) @@ -172,17 +172,25 @@ pollen.error.password.required=Mot de passe obligatoire pollen.error.password2.required=Mot de passe répété obligatoire pollen.error.passwords.not.equals=Les deux mots de passe saisis non identiques +pollen.error.poll.choice.already.used.name=Choix déjà utilisé. +pollen.error.poll.choice.name.required=Le nom du choix est obligatoire. +pollen.error.poll.dateChoice.already.used=Date déjà utilisée. +pollen.error.poll.dateChoice.badDateFormat=Format de date non valide, format jj/MM/aaaa [hh\:mm] (exemple 31/12/2000 23\:59) +pollen.error.poll.dateChoice.required=La saisie d'une date est obligatoire. 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.imageChoice.already.used=Choix d'image déjà utilisé (les noms doivent être tous différents). +pollen.error.poll.imageChoice.upload.required=Le choix d'une image est obligatoire. 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.email.doublon=Courriel déjà utilisé. +pollen.error.poll.personToList.votingId.doublon=nom de votant déjà utilisé. +pollen.error.poll.personToList.votingId.required=Nom de votant obligatoire. 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. Modified: trunk/pollen-ui-struts2/src/main/resources/shiro.ini =================================================================== --- trunk/pollen-ui-struts2/src/main/resources/shiro.ini 2012-06-16 20:33:49 UTC (rev 3493) +++ trunk/pollen-ui-struts2/src/main/resources/shiro.ini 2012-06-16 20:36:03 UTC (rev 3494) @@ -45,6 +45,7 @@ /user/changeLang=anon /user/register**=anon /user/lostPassword**=anon +/poll/create**=anon # connected urls /user/**=connected @@ -70,9 +71,8 @@ /poll/results/**=pollResultAccess # is poll exists and user can admin it (his creator or an admin) -/poll/modification/**=pollCreatorAccess +/poll/edit/**=pollCreatorAccess /poll/summary/**=pollCreatorAccess /poll/moderate/**=pollCreatorAccess /poll/clone/**=pollCreatorAccess -/poll/resultLink/**=pollCreatorAccess /poll/resume/**=pollCreatorAccess \ No newline at end of file Modified: trunk/pollen-ui-struts2/src/main/webapp/WEB-INF/decorators/layout-default.jsp =================================================================== --- trunk/pollen-ui-struts2/src/main/webapp/WEB-INF/decorators/layout-default.jsp 2012-06-16 20:33:49 UTC (rev 3493) +++ trunk/pollen-ui-struts2/src/main/webapp/WEB-INF/decorators/layout-default.jsp 2012-06-16 20:36:03 UTC (rev 3494) @@ -190,7 +190,7 @@ <div class="top_left${pageLogo}"></div> <ul class="top_middle${pageLogo}"> <li> - <s:a action="create" namespace="/poll"> + <s:a action="create" namespace="/poll" method="input"> <s:text name="pollen.menu.createPoll"/> </s:a> </li> Modified: trunk/pollen-ui-struts2/src/main/webapp/WEB-INF/jsp/home.jsp =================================================================== --- trunk/pollen-ui-struts2/src/main/webapp/WEB-INF/jsp/home.jsp 2012-06-16 20:33:49 UTC (rev 3493) +++ trunk/pollen-ui-struts2/src/main/webapp/WEB-INF/jsp/home.jsp 2012-06-16 20:36:03 UTC (rev 3494) @@ -31,7 +31,7 @@ </div> <div class="center"> - <s:a action="create" namespace="/poll"> + <s:a action="create" namespace="/poll" method="input"> <img src="<s:url value='/img/smallCreation_%{safeLanguage}.png' />" alt="poll creation"/> </s:a> <img src="<s:url value='/img/smallVote_%{safeLanguage}.png' />" alt="vote"/> 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-16 20:33:49 UTC (rev 3493) +++ trunk/pollen-ui-struts2/src/main/webapp/WEB-INF/jsp/poll/create.jsp 2012-06-16 20:36:03 UTC (rev 3494) @@ -61,7 +61,7 @@ confirmCloseTitle:"<s:text name='pollen.title.close.poll'/>", confirmCloseUrl:'<s:url action="confirmClosePoll/" namespace="/poll"/>' + '<s:property value="%{poll.adminId}"/>', - confirmCloseRedirectUrl:'<s:url action="resultLink/" namespace="/poll"/>' + confirmCloseRedirectUrl:'<s:url action="summary/" namespace="/poll"/>' + '<s:property value="%{poll.adminId}"/>' } ); @@ -91,7 +91,6 @@ <div id="tgeneral"> <fieldset> - <%--<legend><s:text name="pollen.common.voteCountingType"/></legend>--%> <s:textfield key="poll.title" label="%{getText('pollen.common.title')}" required="true" size="80"/> @@ -171,28 +170,24 @@ disabled="%{voteStarted}" tooltip="%{getText('pollen.common.pollOption.choiceAddAllowed.help')}" tooltipIconPath="/img/tooltip.png"/> - <%--<div id='addChoiceAddAllowedPanel' class="hidden">--%> - <sj:datepicker key="poll.beginChoiceDate" - label="%{getText('pollen.common.beginChoiceDate')}" - displayFormat="%{getText('pollen.common.datePickerPattern')}" - timepicker="true" - disabled="%{voteStarted}"/> - <sj:datepicker key="poll.endChoiceDate" - label="%{getText('pollen.common.endChoiceDate')}" - displayFormat="%{getText('pollen.common.datePickerPattern')}" - timepicker="true" - disabled="%{voteStarted}"/> - <%--</div>--%> + <sj:datepicker key="poll.beginChoiceDate" + label="%{getText('pollen.common.beginChoiceDate')}" + displayFormat="%{getText('pollen.common.datePickerPattern')}" + timepicker="true" + disabled="%{voteStarted}"/> + <sj:datepicker key="poll.endChoiceDate" + label="%{getText('pollen.common.endChoiceDate')}" + displayFormat="%{getText('pollen.common.datePickerPattern')}" + timepicker="true" + disabled="%{voteStarted}"/> <s:checkbox key="limitChoice" label="%{getText('pollen.common.pollOption.limitChoice')}" disabled="%{voteStarted}" tooltip="%{getText('pollen.common.pollOption.limitChoice.help')}" tooltipIconPath="/img/tooltip.png"/> - <%--<div id='maxChoiceNbPanel' class="hidden">--%> - <s:textfield key="maxChoices" - label="%{getText('pollen.common.pollOption.maxChoiceNb')}" - disabled="%{voteStarted}"/> - <%--</div>--%> + <s:textfield key="maxChoices" + label="%{getText('pollen.common.pollOption.maxChoiceNb')}" + disabled="%{voteStarted}"/> </fieldset> <br/> @@ -209,13 +204,14 @@ disabled="%{voteStarted}" tooltip="%{getText('pollen.common.pollOption.anonymous.help')}" tooltipIconPath="/img/tooltip.png"/> - <s:checkbox key="poll.anonymousVoteAllowed" - label="%{getText('pollen.common.pollOption.anonymousVoteAllowed')}" - disabled="%{voteStarted}" - tooltip="%{getText('pollen.common.pollOption.anonymousVoteAllowed.help')}" - tooltipIconPath="/img/tooltip.png"/> - </fieldset> - <br/><fieldset> + <s:checkbox key="poll.anonymousVoteAllowed" + label="%{getText('pollen.common.pollOption.anonymousVoteAllowed')}" + disabled="%{voteStarted}" + tooltip="%{getText('pollen.common.pollOption.anonymousVoteAllowed.help')}" + tooltipIconPath="/img/tooltip.png"/> + </fieldset> + <br/> + <fieldset> <legend> <s:text name="pollen.fieldset.result.options"/> <img src="<s:url value='/img/tooltip.png'/>" class="tooltip" @@ -227,12 +223,10 @@ label="%{getText('pollen.common.pollOption.publicResults')}" tooltip="%{getText('pollen.common.pollOption.publicResults.help')}" tooltipIconPath="/img/tooltip.png"/> - <%--<div id='publicPanel' class="hidden">--%> - <s:checkbox key="poll.continuousResults" - label="%{getText('pollen.common.pollOption.continuousResults')}" - tooltip="%{getText('pollen.common.pollOption.continuousResults.help')}" - tooltipIconPath="/img/tooltip.png"/> - <%--</div>--%> + <s:checkbox key="poll.continuousResults" + label="%{getText('pollen.common.pollOption.continuousResults')}" + tooltip="%{getText('pollen.common.pollOption.continuousResults.help')}" + tooltipIconPath="/img/tooltip.png"/> </fieldset> <br/> @@ -251,10 +245,8 @@ label="%{getText('pollen.common.pollOption.reminder')}" tooltip="%{getText('pollen.common.pollOption.reminder.help')}" tooltipIconPath="/img/tooltip.png"/> - <%--<div id='reminderPanel' class="hidden">--%> - <s:textfield key="reminderHourCountdown" - label="%{getText('pollen.common.pollOption.reminderHourCountdown')}"/> - <%--</div>--%> + <s:textfield key="reminderHourCountdown" + label="%{getText('pollen.common.pollOption.reminderHourCountdown')}"/> </fieldset> <br/> @@ -300,9 +292,8 @@ disabled="%{voteStarted}"/> <s:if test="userLoggued"> <s:submit key="pollen.action.addVotingListFromPersonList" - theme="simple" onclick='return selectPersonListToCreateNewVotingList();' - disabled="%{voteStarted}"/> + theme="simple" disabled="%{voteStarted}"/> </s:if> </div> </div> @@ -312,14 +303,20 @@ </sj:tabbedpanel> <br/> - <s:submit action="save" value="%{actionLabel}" align="center"/> <s:if test="edit"> + <s:submit action="edit/%{uriId}" value="%{actionLabel}" align="center"/> <div align="center" style="margin-top: 10px"> <button onclick="return confirmClose();"> <s:text name="pollen.action.close"/> </button> </div> </s:if> + <s:elseif test="clone"> + <s:submit action="clone/%{uriId}" value="%{actionLabel}" align="center"/> + </s:elseif> + <s:else> + <s:submit action="create" value="%{actionLabel}" align="center"/> + </s:else> </s:form> <script type="text/javascript"> Modified: trunk/pollen-ui-struts2/src/main/webapp/WEB-INF/jsp/poll/createPoll_choices.jsp =================================================================== --- trunk/pollen-ui-struts2/src/main/webapp/WEB-INF/jsp/poll/createPoll_choices.jsp 2012-06-16 20:33:49 UTC (rev 3493) +++ trunk/pollen-ui-struts2/src/main/webapp/WEB-INF/jsp/poll/createPoll_choices.jsp 2012-06-16 20:36:03 UTC (rev 3494) @@ -45,6 +45,7 @@ <s:hidden key='%{#prefix}.topiaId' value='%{#choice.topiaId}' label=''/> <sp:fielderror fieldName="%{#prefix}" id="%{#prefix}_error"/> <div class="fleft choiceName"> + <sp:fielderror fieldName="%{#prefix}.name" id="%{#prefix}.name_error"/> <s:label for="%{#prefix}.name" id="choicesTEXT_label_%{#choiceNumber}" theme="simple" value=''/> <s:textfield cssClass="nameField" id='%{#prefix}.name' @@ -99,13 +100,14 @@ value='%{#choice.topiaId}' label='' theme="simple"/> <sp:fielderror fieldName="%{#prefix}" id="%{#prefix}_error"/> <div class="fleft choiceName"> + <sp:fielderror fieldName="%{#prefix}.name" id="%{#prefix}.name_error"/> <s:label for="%{#prefix}.name" id="choicesDATE_label_%{choiceNumber}" theme="simple" value=''/> <sj:datepicker id='%{#prefix}.name' key="%{#prefix}.name" changeMonth="true" changeYear="true" labelSeparator="" theme="simple" label="" - timepicker="true" value="%{#choice.date}" + timepicker="true" value="%{#choice.name}" displayFormat="%{getText('pollen.common.datePickerPattern')}" disabled="%{voteStarted}"/> - @@ -154,6 +156,7 @@ <s:hidden key='%{#prefix}.topiaId' value='%{#choice.topiaId}' label=''/> <sp:fielderror fieldName="%{#prefix}" id="%{#prefix}_error"/> <div class="fleft choiceName"> + <sp:fielderror fieldName="%{#prefix}.name" id="%{#prefix}.name_error"/> <s:label for="%{#prefix}.name" id="choicesIMAGE_label_%{choiceNumber}" theme="simple" value=''/> <s:if test="#choice.name != null"> @@ -175,8 +178,10 @@ title="<s:property value='name'/>" src="<s:property value='imageUrl'/>"> - <!--s:label label='' theme="simple" cssClass="nameField" - value="%{#choice.name}" readonly="true"/--> + <s:file key='imageChoice[%{#choiceNumber}]' label='' + theme="simple" + cssClass="nameField fleft" + disabled="%{voteStarted}" cssStyle="margin-left:50px;"/> </s:if> <s:else> <%--New image--%> Modified: trunk/pollen-ui-struts2/src/main/webapp/WEB-INF/jsp/poll/result.jsp =================================================================== --- trunk/pollen-ui-struts2/src/main/webapp/WEB-INF/jsp/poll/result.jsp 2012-06-16 20:33:49 UTC (rev 3493) +++ trunk/pollen-ui-struts2/src/main/webapp/WEB-INF/jsp/poll/result.jsp 2012-06-16 20:36:03 UTC (rev 3494) @@ -66,7 +66,7 @@ <legend><s:text name="pollen.common.aboutPoll"/></legend> <div style="float: right"> <s:if test="creatorUser or userAdmin"> - <s:a namespace="/poll" action="modification/%{uriId}"> + <s:a namespace="/poll" action="summary/%{uriId}"> <img src="<s:url value='/img/editSmall.png'/>" title="<s:text name='pollen.action.editPoll'/>" alt="<s:text name='pollen.action.editPoll'/>"/> Deleted: trunk/pollen-ui-struts2/src/main/webapp/WEB-INF/jsp/poll/resultLink.jsp =================================================================== --- trunk/pollen-ui-struts2/src/main/webapp/WEB-INF/jsp/poll/resultLink.jsp 2012-06-16 20:33:49 UTC (rev 3493) +++ trunk/pollen-ui-struts2/src/main/webapp/WEB-INF/jsp/poll/resultLink.jsp 2012-06-16 20:36:03 UTC (rev 3494) @@ -1,46 +0,0 @@ -<%-- - #%L - Pollen :: UI (struts2) - $Id$ - $HeadURL$ - %% - Copyright (C) 2009 - 2012 CodeLutin, Tony Chemit - %% - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. - #L% - --%> -<%@ page language="java" contentType="text/html" pageEncoding="utf-8" %> -<%@ taglib prefix="s" uri="/struts-tags" %> -<h1 class="titleCreation"><s:property value="poll.title"/></h1> - -<h3><s:property value="poll.title"/> <s:text name="pollen.common.by"/> - <s:property value="poll.creator.votingId"/></h3> - -<div style="margin-top: 10px;"> - <img src="<s:url value='/img/count.png'/>" - alt="<s:text name='pollen.common.resultAction'/>" - title="<s:text name='pollen.common.resultAction'/>" - style="margin-right: 18px;"/> - <s:text name='pollen.label.pollResultPage'/> - <br/> - <s:a href="%{pollResultUrl}" cssStyle="margin-left:50px;"> - <s:property value="%{pollResultUrl}"/> - </s:a> -</div> -<div style="margin-top: 30px;"> - <s:text name="pollen.label.pollRegisterPage"/> - <s:a namespace="/user" action="createdList"> - <s:text name="pollen.common.myPolls"/> - </s:a>. -</div> Modified: trunk/pollen-ui-struts2/src/main/webapp/WEB-INF/jsp/poll/summary.jsp =================================================================== --- trunk/pollen-ui-struts2/src/main/webapp/WEB-INF/jsp/poll/summary.jsp 2012-06-16 20:33:49 UTC (rev 3493) +++ trunk/pollen-ui-struts2/src/main/webapp/WEB-INF/jsp/poll/summary.jsp 2012-06-16 20:36:03 UTC (rev 3494) @@ -23,17 +23,20 @@ <%@ page language="java" contentType="text/html" pageEncoding="utf-8" %> <%@ taglib prefix="s" uri="/struts-tags" %> <%@ taglib prefix="sj" uri="/struts-jquery-tags" %> -<link rel="stylesheet" type="text/css" href="<s:url value='/css/summary.css'/>"/> +<link rel="stylesheet" type="text/css" + href="<s:url value='/css/summary.css'/>"/> <script type="text/javascript"> - var redirectUrl = '<s:url namespace="/poll" action="summary/%{uriId}"/>'; function confirmDeletePoll(id) { $('.ui-dialog-title').html("<s:text name="pollen.title.delete.poll"/>"); var dialog = $("#confirmDialog"); dialog.html(''); var url = "<s:url action='confirmDeletePoll/' namespace='/poll'/>"; - url += id + '?' + $.param({redirectUrl:redirectUrl}); + url += id + '?' + $.param( + { + redirectUrl:'<s:url namespace="/poll" action="summary/%{uriId}"/>' + }); dialog.load(url); dialog.dialog('open'); return false; @@ -44,7 +47,10 @@ var dialog = $("#confirmDialog"); dialog.html(''); var url = "<s:url action='confirmClosePoll/' namespace='/poll'/>"; - url += id + '?' + $.param({redirectUrl:redirectUrl}); + url += id + '?' + $.param( + { + redirectUrl:'<s:url namespace="/poll" action="summary/%{uriId}"/>' + }); dialog.load(url); dialog.dialog('open'); return false; @@ -62,7 +68,7 @@ <br/> </div> -<%--Vote action--%> +<%--Vote--%> <s:if test="canVote"> <div class="ui-widget-content-green ui-corner-all"> <img src="<s:url value='/img/vote.png'/>" class="imgAction" @@ -76,10 +82,10 @@ </div> </s:if> -<%--Show Results action--%> +<%--Show Results--%> <s:if test="canShowResult"> <div class="ui-widget-content-green ui-corner-all"> - <img src="<s:url value='/img/count.png'/>" class="imgAction" + <img src="<s:url value='/img/count.png'/>" class="imgAction" alt="<s:text name='pollen.action.pollResult'/>" title="<s:text name='pollen.action.pollResult'/>"/> <s:text name='pollen.label.pollResultPage'/> @@ -90,7 +96,7 @@ </div> </s:if> -<%--Moderate action--%> +<%--Moderate--%> <div class="ui-widget-content-yellow ui-corner-all"> <img src="<s:url value='/img/moderate.png'/>" class="imgAction" alt="<s:text name='pollen.action.pollModerateVote'/>" @@ -102,7 +108,7 @@ </s:a> </div> -<%--Edit action--%> +<%--Edit--%> <div class="ui-widget-content-yellow ui-corner-all"> <img src="<s:url value='/img/edit.png'/>" class="imgAction" alt="<s:text name='pollen.action.editPoll'/>" @@ -114,7 +120,7 @@ </s:a> </div> -<%--Export action--%> +<%--Export--%> <div class="ui-widget-content-blue ui-corner-all"> <img src="<s:url value='/img/export.png'/>" class="imgAction" alt="<s:text name='pollen.action.pollExport'/>" @@ -124,7 +130,7 @@ </s:a> </div> -<%--Clone action--%> +<%--Clone--%> <div class="ui-widget-content-blue ui-corner-all"> <img src="<s:url value='/img/copy.png'/>" class="imgAction" alt="<s:text name='pollen.action.clone'/>" @@ -134,7 +140,7 @@ </s:a> </div> -<%--Close action--%> +<%--Close--%> <s:if test="canClose"> <div class="ui-widget-content-red ui-corner-all"> <img src="<s:url value='/img/close.png'/>" class="imgAction" @@ -147,7 +153,7 @@ </div> </s:if> -<%--Delete action--%> +<%--Delete --%> <div class="ui-widget-content-red ui-corner-all"> <img src="<s:url value='/img/delete.png'/>" class="imgAction" alt="<s:text name='pollen.action.deletePoll'/>" @@ -157,11 +163,4 @@ </s:a> </div> -<%--div style="margin-top: 30px;"> - <s:text name="pollen.label.pollRegisterPage"/> - <s:a namespace="/user" action="createdList"> - <s:text name="pollen.common.myPolls"/> - </s:a>. -</div--%> - <sj:dialog id="confirmDialog" autoOpen="false" modal="true" width="500"/> Modified: trunk/pollen-ui-struts2/src/test/java/org/chorem/pollen/ui/PollenFixtures.java =================================================================== --- trunk/pollen-ui-struts2/src/test/java/org/chorem/pollen/ui/PollenFixtures.java 2012-06-16 20:33:49 UTC (rev 3493) +++ trunk/pollen-ui-struts2/src/test/java/org/chorem/pollen/ui/PollenFixtures.java 2012-06-16 20:36:03 UTC (rev 3494) @@ -115,22 +115,6 @@ return baseUrl() + "security/admin_required"; } - public String voteforURL() { - return baseUrl() + "poll/votefor/"; - } - - public String voteforURL(PollUri pollUri) { - return voteforURL() + pollUri.toString(); - } - - public String modificationURL(PollUri pollUri) { - return modificationURL() + pollUri.toString(); - } - - public String modificationURL() { - return baseUrl() + "poll/modification/"; - } - public String poll_requiredURL() { return baseUrl() + "security/illegal_access"; } @@ -143,12 +127,20 @@ return baseUrl() + "security/illegal_access"; } + public String voteforURL(PollUri pollUri) { + return baseUrl() + "poll/votefor/" + pollUri.toString(); + } + + public String editURL(PollUri pollUri) { + return baseUrl() + "poll/edit/" + pollUri.toString() + "!input"; + } + public String createPollURL() { return baseUrl() + "poll/create"; } - public String savePollURL() { - return baseUrl() + "poll/save"; + public String editPollURL() { + return baseUrl() + "poll/edit"; } public String summaryURL() { Modified: trunk/pollen-ui-struts2/src/test/java/org/chorem/pollen/ui/its/CreateFreeTextPollSIT.java =================================================================== --- trunk/pollen-ui-struts2/src/test/java/org/chorem/pollen/ui/its/CreateFreeTextPollSIT.java 2012-06-16 20:33:49 UTC (rev 3493) +++ trunk/pollen-ui-struts2/src/test/java/org/chorem/pollen/ui/its/CreateFreeTextPollSIT.java 2012-06-16 20:36:03 UTC (rev 3494) @@ -471,8 +471,7 @@ submit.click(); // No choices, should stay on create poll page - //FIXME-tchemit-2012-06-15 (see http://chorem.org/issues/618) - checkCurrentUrl(fixtures.savePollURL(), false); + checkCurrentUrl(fixtures.createPollURL(), false); } Modified: trunk/pollen-ui-struts2/src/test/java/org/chorem/pollen/ui/its/SecurityAccessSIT.java =================================================================== --- trunk/pollen-ui-struts2/src/test/java/org/chorem/pollen/ui/its/SecurityAccessSIT.java 2012-06-16 20:33:49 UTC (rev 3493) +++ trunk/pollen-ui-struts2/src/test/java/org/chorem/pollen/ui/its/SecurityAccessSIT.java 2012-06-16 20:36:03 UTC (rev 3494) @@ -243,11 +243,11 @@ gotoUrl(fixtures.voteforURL(PollUri.newPollUri(pollId, badCreatorId)), fixtures.poll_access_requiredURL(), false); // try to access to poll moderation page, current url should be good one - String normalPollAdminURL = fixtures.modificationURL(PollUri.newPollUri(pollId, creatorId)); + String normalPollAdminURL = fixtures.editURL(PollUri.newPollUri(pollId, creatorId)); gotoUrl(normalPollAdminURL); // try to access to poll page with bad pollId, current url should be the poll_required one - gotoUrl(fixtures.modificationURL(PollUri.newPollUri(pollId, badCreatorId)), fixtures.poll_creator_requiredURL(), false); + gotoUrl(fixtures.editURL(PollUri.newPollUri(pollId, badCreatorId)), fixtures.poll_creator_requiredURL(), false); } /** @@ -295,15 +295,15 @@ gotoUrl(fixtures.voteforURL(PollUri.newPollUri(pollId, badCreatorId)), fixtures.poll_access_requiredURL(), false); // try to access to poll modification page without creator Id, current url should be good one (admin access) - String simpleNormalPollAdminURL = fixtures.modificationURL(PollUri.newPollUri(pollId)); + String simpleNormalPollAdminURL = fixtures.editURL(PollUri.newPollUri(pollId)); gotoUrl(simpleNormalPollAdminURL); // try to access to poll modification page with creator Id, current url should be good one - String normalPollAdminURL = fixtures.modificationURL(PollUri.newPollUri(pollId, creatorId)); + String normalPollAdminURL = fixtures.editURL(PollUri.newPollUri(pollId, creatorId)); gotoUrl(normalPollAdminURL); // try to access to poll modifcation page with bad creatorId, current url should be the poll_creator_required one, even if we are admin - gotoUrl(fixtures.modificationURL(PollUri.newPollUri(pollId, badCreatorId)), fixtures.poll_creator_requiredURL(), false); + gotoUrl(fixtures.editURL(PollUri.newPollUri(pollId, badCreatorId)), fixtures.poll_creator_requiredURL(), false); } /** @@ -351,15 +351,15 @@ gotoUrl(fixtures.voteforURL(PollUri.newPollUri(pollId, badCreatorId)), fixtures.poll_access_requiredURL(), false); // try to access to poll modification page without creator Id, current url should be good one (owner access) - String simpleNormalPollModificationURL = fixtures.modificationURL(PollUri.newPollUri(pollId)); + String simpleNormalPollModificationURL = fixtures.editURL(PollUri.newPollUri(pollId)); gotoUrl(simpleNormalPollModificationURL); // try to access to poll modification page with creator Id, current url should be good one - String normalPollModificationURL = fixtures.modificationURL(PollUri.newPollUri(pollId, creatorId)); + String normalPollModificationURL = fixtures.editURL(PollUri.newPollUri(pollId, creatorId)); gotoUrl(normalPollModificationURL); // try to access to poll modifcation page with bad creatorId, current url should be the poll_creator_required one, even if we are owner - gotoUrl(fixtures.modificationURL(PollUri.newPollUri(pollId, badCreatorId)), fixtures.poll_creator_requiredURL(), false); + gotoUrl(fixtures.editURL(PollUri.newPollUri(pollId, badCreatorId)), fixtures.poll_creator_requiredURL(), false); } }
participants (1)
-
tchemit@users.chorem.org