Author: kmorin Date: 2013-06-26 19:50:48 +0200 (Wed, 26 Jun 2013) New Revision: 3840 Url: http://chorem.org/projects/pollen/repository/revisions/3840 Log: continue (poll creation form + login and logout) Added: trunk/pollen-ui-js/src/main/webapp/css/bootstrap-datetimepicker.min.css trunk/pollen-ui-js/src/main/webapp/js/libs/bootstrap-datetimepicker.min.js trunk/pollen-ui-js/src/main/webapp/js/models/choices.js trunk/pollen-ui-js/src/main/webapp/js/pollen-utils.js Modified: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenRender.java trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenServiceContextFilter.java trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenServiceListener.java trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/ChoiceService.java trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/PollService.java trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/AuthService.java trunk/pollen-ui-js/src/main/webapp/bundle/Messages.properties trunk/pollen-ui-js/src/main/webapp/index.html trunk/pollen-ui-js/src/main/webapp/js/controls/poll_form.js trunk/pollen-ui-js/src/main/webapp/js/controls/poll_list.js trunk/pollen-ui-js/src/main/webapp/js/controls/poll_summary.js trunk/pollen-ui-js/src/main/webapp/js/controls/vote.js trunk/pollen-ui-js/src/main/webapp/js/models/comments.js trunk/pollen-ui-js/src/main/webapp/js/models/polls.js trunk/pollen-ui-js/src/main/webapp/js/models/votes.js trunk/pollen-ui-js/src/main/webapp/views/poll_form.ejs trunk/pollen-ui-js/src/main/webapp/views/vote.ejs Modified: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenRender.java =================================================================== --- trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenRender.java 2013-06-21 21:26:23 UTC (rev 3839) +++ trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenRender.java 2013-06-26 17:50:48 UTC (rev 3840) @@ -47,7 +47,9 @@ import java.lang.annotation.Target; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.lang.reflect.Type; import java.util.Collections; +import java.util.Date; import java.util.List; import java.util.Map; @@ -92,7 +94,16 @@ } Object map = toMap(model, includeCollection); - Gson gson = new GsonBuilder().create(); + Gson gson = new GsonBuilder().registerTypeAdapter(Date.class, new JsonSerializer<Date>() { + @Override + public JsonElement serialize(Date src, Type typeOfSrc, JsonSerializationContext context) { + if(src == null) { + return JsonNull.INSTANCE; + } + return new JsonPrimitive(src.getTime()); + } + + }).create(); String json = gson.toJson(map); PrintWriter out = context.getOut(); out.print(json); Modified: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenServiceContextFilter.java =================================================================== --- trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenServiceContextFilter.java 2013-06-21 21:26:23 UTC (rev 3839) +++ trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenServiceContextFilter.java 2013-06-26 17:50:48 UTC (rev 3840) @@ -70,7 +70,7 @@ String[] strings = context.getParameters().get(REQUEST_AUTH_PARAMETER); - String authParam = strings == null || strings.length < 1 ? null : strings[1]; + String authParam = strings == null || strings.length < 1 ? null : strings[0]; SessionToken sessionToken = null; Modified: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenServiceListener.java =================================================================== --- trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenServiceListener.java 2013-06-21 21:26:23 UTC (rev 3839) +++ trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenServiceListener.java 2013-06-26 17:50:48 UTC (rev 3840) @@ -23,6 +23,8 @@ * #L% */ +import org.apache.commons.beanutils.Converter; +import org.apache.commons.lang3.ClassUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.chorem.pollen.services.PollenServiceContext; @@ -38,6 +40,7 @@ import javax.persistence.EntityManager; import javax.servlet.http.HttpServletRequest; import java.lang.reflect.Type; +import java.util.Date; /** * TODO @@ -53,7 +56,24 @@ @Override public void onStart(Mapping mapping, ServerContext serverContext) { + serverContext.addConverter(new Converter() { + @Override + public Object convert(Class type, Object value) { + Object result = null; + if (value != null) { + if (value.getClass().isAssignableFrom(Date.class)) { + result = value; + } else { + Object o = ((Object[]) value)[0]; + String sTime = o.toString(); + Long time = Long.parseLong(sTime); + result = new Date(time); + } + } + return result; + } + }, Date.class); serverContext.addInjector(new PollenServiceContextInjector()); // Create application context Modified: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/ChoiceService.java =================================================================== --- trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/ChoiceService.java 2013-06-21 21:26:23 UTC (rev 3839) +++ trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/ChoiceService.java 2013-06-26 17:50:48 UTC (rev 3840) @@ -40,7 +40,7 @@ public class ChoiceService extends WebMotionController { public List<Choice> getChoices(PollenServiceContext context, String pollId) throws EntityNotFoundException { - context.getSecurityService().prepareSubject(pollId); + context.getSecurityService().prepareSubject((String) null); List<Choice> choices = context.getChoiceService().getChoices(pollId); return choices; } Modified: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/PollService.java =================================================================== --- trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/PollService.java 2013-06-21 21:26:23 UTC (rev 3839) +++ trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/PollService.java 2013-06-26 17:50:48 UTC (rev 3840) @@ -66,7 +66,7 @@ } public Poll getPoll(PollenServiceContext context, String pollId) throws EntityNotFoundException { - context.getSecurityService().prepareSubject(pollId); + context.getSecurityService().prepareSubject((String)null); return context.getPollService().getPoll(pollId); } Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/AuthService.java =================================================================== --- trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/AuthService.java 2013-06-21 21:26:23 UTC (rev 3839) +++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/AuthService.java 2013-06-26 17:50:48 UTC (rev 3840) @@ -90,11 +90,10 @@ getUserService().getUserByLogin(login); - String encodedToken = serviceContext.encodePassword(token); SessionTokenJpaDao dao = getPersistenceContext().getSessionTokenDao(); - SessionToken sessionToken = dao.findByToken(encodedToken); + SessionToken sessionToken = dao.findById(token); checkEntityExists(SessionToken.class, sessionToken, token); dao.remove(sessionToken); @@ -103,7 +102,7 @@ public SessionToken getUserByAuth(String authParam) throws InvalidSessionTokenException { - SessionToken sessionToken = getPersistenceContext().getSessionTokenDao().findByToken(authParam); + SessionToken sessionToken = getPersistenceContext().getSessionTokenDao().findById(authParam); if (sessionToken == null) { throw new InvalidSessionTokenException(); } Modified: trunk/pollen-ui-js/src/main/webapp/bundle/Messages.properties =================================================================== --- trunk/pollen-ui-js/src/main/webapp/bundle/Messages.properties 2013-06-21 21:26:23 UTC (rev 3839) +++ trunk/pollen-ui-js/src/main/webapp/bundle/Messages.properties 2013-06-26 17:50:48 UTC (rev 3840) @@ -25,8 +25,10 @@ #common pollen.common.cancel=Annuler pollen.common.validate=Valider -pollen.common.format.date=DD/MM/YYYY -pollen.common.format.dateTime=DD/MM/YYYY HH:mm +pollen.common.format.date.moment=DD/MM/YYYY +pollen.common.format.dateTime.moment=DD/MM/YYYY HH:mm +pollen.common.format.date.input=dd/MM/yyyy +pollen.common.format.dateTime.input=dd/MM/yyyy hh:mm pollen.common.format.time=HH:mm pollen.common.date.from=à partir du {0} pollen.common.date.fromTo=du {0} au {1} @@ -37,12 +39,66 @@ pollen.poll.description.placeholder=Description pollen.poll.title.label=Titre pollen.poll.title.placeholder=Titre +pollen.poll.voteCountingType.label=Type de dépouillement +pollen.poll.creator.name.label=Votre nom +pollen.poll.creator.name.placeholder=Votre nom +pollen.poll.creator.email.label=Votre email +pollen.poll.creator.email.placeholder=Votre email +pollen.poll.choice.name.label=Nom +pollen.poll.choice.name.placeholder=Nom +pollen.poll.choice.description.label=Description +pollen.poll.choice.description.placeholder=Description +pollen.poll.beginDate.label=Date de début +pollen.poll.beginDate.placeholder=Date de début +pollen.poll.endDate.label=Date de fin +pollen.poll.endDate.placeholder=Date de fin +pollen.poll.choiceAddAllowed.label=Autoriser l'ajout de choix +pollen.poll.addChoiceBeginDate.label=Date de début d'ajout de choix +pollen.poll.addChoiceBeginDate.placeholder=Date de début d'ajout de choix +pollen.poll.addChoiceEndDate.label=Date de fin d'ajout de choix +pollen.poll.addChoiceEndDate.placeholder=Date de fin d'ajout de choix +pollen.poll.maxChoiceNumber.label=Nombre limite de choix par vote +pollen.poll.maxChoiceNumber.placeholder=Laisser vide ou 0 pour ne pas fixer de limite +pollen.poll.commentVisibility.label=Visibilité des commentaires +pollen.poll.commentVisibility.everybody.label=Publique +pollen.poll.commentVisibility.voter.label=Seulement les votants +pollen.poll.commentVisibility.nobody.label=Aucun commentaires +pollen.poll.voteVisibility.label=Visibilité des votes +pollen.poll.voteVisibility.everybody.label=Publique +pollen.poll.voteVisibility.voter.label=Votants +pollen.poll.voteVisibility.creator.label=Créateur +pollen.poll.voteVisibility.anonymous.label=Anonyme +pollen.poll.anonymousVoteAllowed.label=Vote anonyme +pollen.poll.pollType.label=Qui peut voter ? +pollen.poll.pollType.free.label=Libre +pollen.poll.pollType.restricted.label=Restreint +pollen.poll.pollType.group.label=Groupe +pollen.poll.resultVisibility.label=Visibilité des résultats +pollen.poll.resultVisibility.everybody.label=Publique +pollen.poll.resultVisibility.voter.label=Seulement les votants +pollen.poll.resultVisibility.creator.label=Créateur +pollen.poll.continuousResults.label=Résultats continus #choice attributes pollen.choice.description.label=Description pollen.choice.description.placeholder=Description +pollen.choice.noDescription=Aucune description pollen.choice.name.label=Titre pollen.choice.name.placeholder=Titre +pollen.choice.voteType.normal.label=Normal +pollen.choice.voteType.normal.description=Voter pour le ou les choix préférés. +pollen.choice.voteType.percentage.label=Pourcentage +pollen.choice.voteType.percentage.description=Répartir les choix de manière à obtenir 100% au total. +pollen.choice.voteType.condorcet.label=Condorcet +pollen.choice.voteType.condorcet.description=Classer les choix par ordre de préférence de 1 à N (1=préféré).<br/>Seul l'ordre des choix compte, peu importe les valeurs. Deux choix peuvent avoir la même valeur.<br/><a href='http://fr.wikipedia.org/wiki/Méthode_Condorcet'>Pour en savoir plus</a> +pollen.choice.voteType.number.label=Nombre +pollen.choice.voteType.number.description=La réponse est libre, laissez vide ou entrez un nombre entier +pollen.choice.voteType.borda.label=Borda +pollen.choice.voteType.borda.description=Classer les choix par ordre de préférence de 1 à N (1=préféré).<br/>Seul l'ordre des choix compte, peu importe les valeurs. Deux choix peuvent avoir la même valeur.<br/><a href='http://fr.wikipedia.org/wiki/Méthode_Borda'>Pour en savoir plus</a> +pollen.choice.voteType.alternative.label=Vote alternatif +pollen.choice.voteType.alternative.description=Classer les choix par ordre de préférence de 1 à N (1=préféré).<br/>Seul l'ordre des choix compte, peu importe les valeurs. Deux choix peuvent avoir la même valeur.<br/><a href='http://fr.wikipedia.org/wiki/Vote_alternatif'>Pour en savoir plus</a> +pollen.choice.voteType.coombs.label=Coombs +pollen.choice.voteType.coombs.description=Classer les choix par ordre de préférence de 1 à N (1=préféré).<br/>Seul l'ordre des choix compte, peu importe les valeurs. Deux choix peuvent avoir la même valeur.<br/><a href='http://fr.wikipedia.org/wiki/Méthode_de_Coombs'>Pour en savoir plus</a> #user attributes pollen.user.email.label=Email @@ -74,9 +130,15 @@ #poll creation form pollen.poll.form.create.button.save=Créer le sondage +pollen.poll.form.create.button.next=Suivant +pollen.poll.form.create.button.addChoice=Ajouter un choix pollen.poll.form.create.field.title.label=Titre pollen.poll.form.create.field.title.placeholder=Titre pollen.poll.form.create.title=Création de sondage +pollen.poll.form.create.legend.validityDates=Plage de validité +pollen.poll.form.create.legend.choices=Choix +pollen.poll.form.create.legend.votes=Votes +pollen.poll.form.create.legend.results=Resultats #poll lists pollen.polls.created.title=Sondages créés Added: trunk/pollen-ui-js/src/main/webapp/css/bootstrap-datetimepicker.min.css =================================================================== --- trunk/pollen-ui-js/src/main/webapp/css/bootstrap-datetimepicker.min.css (rev 0) +++ trunk/pollen-ui-js/src/main/webapp/css/bootstrap-datetimepicker.min.css 2013-06-26 17:50:48 UTC (rev 3840) @@ -0,0 +1,8 @@ +/*! + * Datepicker for Bootstrap + * + * Copyright 2012 Stefan Petre + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * + */.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;content:"";line-height:0}.clearfix:after{clear:both}.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.bootstrap-datetimepicker-widget{top:0;left:0;width:250px;padding:4px;margin-top:1px;z-index:3000;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.bootstrap-datetimepicker-widget:before{content:'';display:inline-block;border-left:7px solid transparent;border-right:7px solid transparent;border-bottom:7px solid #ccc;border-bottom-color:rgba(0,0,0,0.2);position:absolute;top:-7px;left:6px}.bootstrap-datetimepicker-widget:after{content:'';display:inline-block;border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:6px solid #fff;position:absolute;top:-6px;left:7px}.bootstrap-datetimepicker-widget.pull-right:before{left:auto;right:6px}.bootstrap-datetimepicker-widget.pull-right:after{left:auto;right:7px}.bootstrap-datetimepicker-widget>ul{list-style-type:none;margin:0}.bootstrap-datetimepicker-widget .timepicker-hour,.bootstrap-datetimepicker-widget .timepicker-minute,.bootstrap-datetimepicker-widget .timepicker-second{width:100%;font-weight:bold;font-size:1.2em}.bootstrap-datetimepicker-widget table[data-hour-format="12"] .separator{width:4px;padding:0;margin:0}.bootstrap-datetimepicker-widget .datepicker>div{display:none}.bootstrap-datetimepicker-widget .picker-switch{text-align:center}.bootstrap-datetimepicker-widget table{width:100%;margin:0}.bootstrap-datetimepicker-widget td,.bootstrap-datetimepicker-widget th{text-align:center;width:20px;height:20px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.bootstrap-datetimepicker-widget td.day:hover,.bootstrap-datetimepicker-widget td.hour:hover,.bootstrap-datetimepicker-widget td.minute:hover,.bootstrap-datetimepicker-widget td.second:hover{background:#eee;cursor:pointer}.bootstrap-datetimepicker-widget td.old,.bootstrap-datetimepicker-widget td.new{color:#999}.bootstrap-datetimepicker-widget td.active,.bootstrap-datetimepicker-widget td.active:hover{color:#fff;background-color:#006dcc;background-image:-moz-linear-gradient(top,#08c,#04c);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#04c));background-image:-webkit-linear-gradient(top,#08c,#04c);background-image:-o-linear-gradient(top,#08c,#04c);background-image:linear-gradient(to bottom,#08c,#04c);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc',endColorstr='#ff0044cc',GradientType=0);border-color:#04c #04c #002a80;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);*background-color:#04c;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.bootstrap-datetimepicker-widget td.active:hover,.bootstrap-datetimepicker-widget td.active:hover:hover,.bootstrap-datetimepicker-widget td.active:active,.bootstrap-datetimepicker-widget td.active:hover:active,.bootstrap-datetimepicker-widget td.active.active,.bootstrap-datetimepicker-widget td.active:hover.active,.bootstrap-datetimepicker-widget td.active.disabled,.bootstrap-datetimepicker-widget td.active:hover.disabled,.bootstrap-datetimepicker-widget td.active[disabled],.bootstrap-datetimepicker-widget td.active:hover[disabled]{color:#fff;background-color:#04c;*background-color:#003bb3}.bootstrap-datetimepicker-widget td.active:active,.bootstrap-datetimepicker-widget td.active:hover:active,.bootstrap-datetimepicker-widget td.active.active,.bootstrap-datetimepicker-widget td.active:hover.active{background-color:#039 \9}.bootstrap-datetimepicker-widget td.disabled,.bootstrap-datetimepicker-widget td.disabled:hover{background:0;color:#999;cursor:not-allowed}.bootstrap-datetimepicker-widget td span{display:block;width:47px;height:54px;line-height:54px;float:left;margin:2px;cursor:pointer;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.bootstrap-datetimepicker-widget td span:hover{background:#eee}.bootstrap-datetimepicker-widget td span.active{color:#fff;background-color:#006dcc;background-image:-moz-linear-gradient(top,#08c,#04c);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#04c));background-image:-webkit-linear-gradient(top,#08c,#04c);background-image:-o-linear-gradient(top,#08c,#04c);background-image:linear-gradient(to bottom,#08c,#04c);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc',endColorstr='#ff0044cc',GradientType=0);border-color:#04c #04c #002a80;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);*background-color:#04c;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.bootstrap-datetimepicker-widget td span.active:hover,.bootstrap-datetimepicker-widget td span.active:active,.bootstrap-datetimepicker-widget td span.active.active,.bootstrap-datetimepicker-widget td span.active.disabled,.bootstrap-datetimepicker-widget td span.active[disabled]{color:#fff;background-color:#04c;*background-color:#003bb3}.bootstrap-datetimepicker-widget td span.active:active,.bootstrap-datetimepicker-widget td span.active.active{background-color:#039 \9}.bootstrap-datetimepicker-widget td span.old{color:#999}.bootstrap-datetimepicker-widget td span.disabled,.bootstrap-datetimepicker-widget td span.disabled:hover{background:0;color:#999;cursor:not-allowed}.bootstrap-datetimepicker-widget th.switch{width:145px}.bootstrap-datetimepicker-widget th.next,.bootstrap-datetimepicker-widget th.prev{font-size:21px}.bootstrap-datetimepicker-widget th.disabled,.bootstrap-datetimepicker-widget th.disabled:hover{background:0;color:#999;cursor:not-allowed}.bootstrap-datetimepicker-widget thead tr:first-child th{cursor:pointer}.bootstrap-datetimepicker-widget thead tr:first-child th:hover{background:#eee}.input-append.date .add-on i,.input-prepend.date .add-on i{display:block;cursor:pointer;width:16px;height:16px}.bootstrap-datetimepicker-widget.left-oriented:before{left:auto;right:6px}.bootstrap-datetimepicker-widget.left-oriented:after{left:auto;right:7px} \ No newline at end of file Modified: trunk/pollen-ui-js/src/main/webapp/index.html =================================================================== --- trunk/pollen-ui-js/src/main/webapp/index.html 2013-06-21 21:26:23 UTC (rev 3839) +++ trunk/pollen-ui-js/src/main/webapp/index.html 2013-06-26 17:50:48 UTC (rev 3840) @@ -26,6 +26,7 @@ <meta charset="utf-8"/> <title>Pollen</title> <link rel="stylesheet" href="pollen-ui-js.css"></link> + <link rel="stylesheet" href="css/bootstrap-datetimepicker.min.css"></link> <link rel="stylesheet" href="css/style.css"></link> </head> @@ -51,19 +52,11 @@ <script src="pollen-ui-js.js"></script> <script src="js/libs/jquery.scrollto.js"></script> + <script src="js/libs/bootstrap-datetimepicker.min.js"></script> + <script src="js/pollen-utils.js"></script> - <script type="text/javascript"> - var backendUrl = 'http://localhost:8080/pollen/v1'; - var paramForWM = function(obj, objName) { - var result = ""; - for (var k in obj) { - result += objName + '.' + k + '=' + obj[k] + '&'; - } - return result; - } - </script> - <script src="js/models/polls.js"></script> + <script src="js/models/choices.js"></script> <script src="js/models/comments.js"></script> <script src="js/models/votes.js"></script> <script src="js/models/users.js"></script> Modified: trunk/pollen-ui-js/src/main/webapp/js/controls/poll_form.js =================================================================== --- trunk/pollen-ui-js/src/main/webapp/js/controls/poll_form.js 2013-06-21 21:26:23 UTC (rev 3839) +++ trunk/pollen-ui-js/src/main/webapp/js/controls/poll_form.js 2013-06-26 17:50:48 UTC (rev 3840) @@ -23,36 +23,84 @@ var PollForm = can.Control({ defaults: { - poll: new Poll() + poll: new Poll({ choiceAddAllowed: true }), + choices: new Choice.List([{}, {}]), + process: new can.Observe({ + step: 1 + }) } }, { + init: function() { + var self = this; this.element.html(can.view('views/poll_form.ejs', { - poll: this.options.poll + poll: this.options.poll, + choices: this.options.choices, + process: this.options.process })); + this.options.process.delegate('step', 'change', function(ev, prop, how, newVal, oldVal) { + var breadcrumbs = self.element.find('.breadcrumb li'); + breadcrumbs.each(function() { + var li = $(this); + if (li.data('step') == newVal) { + li.addClass("active"); + li.find('.step').removeClass("btn-link"); + } else { + li.removeClass("active"); + if (li.data('step') < newVal) { + li.find('.step').addClass("btn-link"); + } + } + }); + + var div = self.element.find(".step" + newVal); + div.siblings().hide(); + div.show(); + }); + + this.options.poll.delegate('voteCountingType', 'change', function(ev, prop, how, newVal, oldVal) { + var toSelectOption = self.element.find('[name="voteCountingType"] [value=' + newVal + ']'); + toSelectOption.attr('selected', 'selected'); + $('#pollCreationFormVoteCountingTypeHelp').html(pollen.choice.voteType[toSelectOption.data('description')].description); + }); + + this.options.poll.delegate('choiceAddAllowed', 'change', function(ev, prop, how, newVal, oldVal) { + $('.dateTimePicker.addChoiceDate').each(function() { + if (newVal) { + $(this).data('datetimepicker').enable(); + } else { + $(this).data('datetimepicker').disable(); + } + }); + }); }, ':type/:action route': function(data) { if (data.type === "poll" && data.action === "create") { - var self = this; - $.when(can.ajax(backendUrl + "/polls/new", { - data: { - choiceType: "TEXT", - userId: currentUser.id - } - })).then(function(poll) { - console.log(poll) - self.editPoll(new Poll(poll)); - }); + if (data.step) { + this.options.process.attr('step', data.step); + this.element.show(); + + } else { + var self = this; + $.when(can.ajax(backendUrl + "/polls/new", { + data: { + choiceType: "TEXT", + userId: currentUser.id + } + })).then(function(pollData) { + var poll = new Poll(pollData); + self.editPoll(poll); + }); + } } }, ':type/:id/:action route': function(data) { if (data.type === "poll" && data.action === "edit") { - var self = this; $.when(Poll.findOne({id: data.id})).then( function(poll) { self.editPoll(poll); @@ -60,11 +108,44 @@ } }, + '.breadcrumb .step click': function(el) { + var step = el.parent().data('step'); + if (step < this.options.process.step) { + this.options.process.attr('step', step); + } + }, + + 'button.nextStep click': function() { + var process = this.options.process; + process.attr('step', process.step + 1); + }, + + '.dateTimePicker changeDate': function(el, e) { + var input = el.find('input'); + var owner = input.data('owner'); + owner.attr(input.attr('name'), e.localDate.getTime()); + }, + + ':input:not(:checkbox):not(:checkbox) change': function(el) { + var owner = el.data('owner'); + owner.attr(el.attr('name'), el.val()); + }, + + ':checkbox change': function(el) { + var owner = el.data('owner'); + owner.attr(el.attr('name'), el.prop('checked')); + }, + + '.addChoice click': function() { + this.options.choices.push({}); + }, + '#pollCreationForm submit': function(form) { - var values = can.deparam(form.serialize()), - self = this; + var self = this; - this.options.poll.attr(values).save(function(data) { + this.options.poll.attr('choice', this.options.choices); + + this.options.poll.save(function(data) { if (data.id) { self.options.poll.id = data.id; } @@ -77,6 +158,7 @@ editPoll: function(poll) { this.options.poll.attr(poll._data, true); this.element.siblings().hide(); + this.options.process.attr('step', 3); this.element.show(); } Modified: trunk/pollen-ui-js/src/main/webapp/js/controls/poll_list.js =================================================================== --- trunk/pollen-ui-js/src/main/webapp/js/controls/poll_list.js 2013-06-21 21:26:23 UTC (rev 3839) +++ trunk/pollen-ui-js/src/main/webapp/js/controls/poll_list.js 2013-06-26 17:50:48 UTC (rev 3840) @@ -37,7 +37,7 @@ ':type/:action route': function(data) { if (data.type === "polls") { var self = this; - $.when(Poll.findAll()).then( + $.when(Poll.findAll({ category: 'created', userId: currentUser.id })).then( function(polls) { self.updatePolls(polls); }); Modified: trunk/pollen-ui-js/src/main/webapp/js/controls/poll_summary.js =================================================================== --- trunk/pollen-ui-js/src/main/webapp/js/controls/poll_summary.js 2013-06-21 21:26:23 UTC (rev 3839) +++ trunk/pollen-ui-js/src/main/webapp/js/controls/poll_summary.js 2013-06-26 17:50:48 UTC (rev 3840) @@ -39,7 +39,7 @@ ':type/:id/:action route': function(data) { if (data.type === "poll" && data.action === "summary") { var self = this; - $.when(Poll.findOne({id: data.id})).then( + $.when(Poll.findOne({id: data.id, auth: currentUser.token})).then( function(poll) { self.updateSummary(poll); }); Modified: trunk/pollen-ui-js/src/main/webapp/js/controls/vote.js =================================================================== --- trunk/pollen-ui-js/src/main/webapp/js/controls/vote.js 2013-06-21 21:26:23 UTC (rev 3839) +++ trunk/pollen-ui-js/src/main/webapp/js/controls/vote.js 2013-06-26 17:50:48 UTC (rev 3840) @@ -28,10 +28,11 @@ if (data.type === "poll" && data.action === "vote") { var self = this; $.when(Poll.findOne({id: data.id}), + Choice.findAll({pollId: data.id}), Comment.findAll({pollId: data.id}), Vote.findAll({pollId: data.id})).then( - function(poll, comments, votes) { - self.showPoll(poll, comments, votes); + function(poll, choices, comments, votes) { + self.showPoll(poll, choices, comments, votes); }); } }, @@ -137,11 +138,11 @@ // other functions - showPoll: function(poll, comments, votes) { + showPoll: function(poll, choices, comments, votes) { var results = new can.Observe.List(); // init results - for (var i = 0 ; i < poll.choices.length ; i++) { - results[poll.choices[i].id] = 0; + for (var i = 0 ; i < choices.length ; i++) { + results[choices[i].id] = 0; } // fill the results for (i = 0 ; i < votes.length ; i++) { @@ -160,11 +161,13 @@ poll.results = results; this.options.poll = poll; + this.options.choices = choices; this.options.votes = votes; this.options.comments = comments; this.element.html(can.view('views/vote.ejs', { poll: poll, + choices: choices, comments: comments, votes: votes, currentUser: currentUser Added: trunk/pollen-ui-js/src/main/webapp/js/libs/bootstrap-datetimepicker.min.js =================================================================== --- trunk/pollen-ui-js/src/main/webapp/js/libs/bootstrap-datetimepicker.min.js (rev 0) +++ trunk/pollen-ui-js/src/main/webapp/js/libs/bootstrap-datetimepicker.min.js 2013-06-26 17:50:48 UTC (rev 3840) @@ -0,0 +1,26 @@ +/** + * @license + * ========================================================= + * bootstrap-datetimepicker.js + * http://www.eyecon.ro/bootstrap-datepicker + * ========================================================= + * Copyright 2012 Stefan Petre + * + * Contributions: + * - Andrew Rowls + * - Thiago de Arruda + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ========================================================= + */ +(function($){var smartPhone=window.orientation!=undefined;var DateTimePicker=function(element,options){this.id=dpgId++;this.init(element,options)};var dateToDate=function(dt){if(typeof dt==="string"){return new Date(dt)}return dt};DateTimePicker.prototype={constructor:DateTimePicker,init:function(element,options){var icon;if(!(options.pickTime||options.pickDate))throw new Error("Must choose at least one picker");this.options=options;this.$element=$(element);this.language=options.language in dates?options.language:"en";this.pickDate=options.pickDate;this.pickTime=options.pickTime;this.isInput=this.$element.is("input");this.component=false;if(this.$element.find(".input-append")||this.$element.find(".input-prepend"))this.component=this.$element.find(".add-on");this.format=options.format;if(!this.format){if(this.isInput)this.format=this.$element.data("format");else this.format=this.$element.find("input").data("format");if(!this.format)this.format="MM/dd/yyyy"}this._compileFormat();if(this.component){icon=this.component.find("i")}if(this.pickTime){if(icon&&icon.length)this.timeIcon=icon.data("time-icon");if(!this.timeIcon)this.timeIcon="icon-time";icon.addClass(this.timeIcon)}if(this.pickDate){if(icon&&icon.length)this.dateIcon=icon.data("date-icon");if(!this.dateIcon)this.dateIcon="icon-calendar";icon.removeClass(this.timeIcon);icon.addClass(this.dateIcon)}this.widget=$(getTemplate(this.timeIcon,options.pickDate,options.pickTime,options.pick12HourFormat,options.pickSeconds,options.collapse)).appendTo("body");this.minViewMode=options.minViewMode||this.$element.data("date-minviewmode")||0;if(typeof this.minViewMode==="string"){switch(this.minViewMode){case"months":this.minViewMode=1;break;case"years":this.minViewMode=2;break;default:this.minViewMode=0;break}}this.viewMode=options.viewMode||this.$element.data("date-viewmode")||0;if(typeof this.viewMode==="string"){switch(this.viewMode){case"months":this.viewMode=1;break;case"years":this.viewMode=2;break;default:this.viewMode=0;break}}this.startViewMode=this.viewMode;this.weekStart=options.weekStart||this.$element.data("date-weekstart")||0;this.weekEnd=this.weekStart===0?6:this.weekStart-1;this.setStartDate(options.startDate||this.$element.data("date-startdate"));this.setEndDate(options.endDate||this.$element.data("date-enddate"));this.fillDow();this.fillMonths();this.fillHours();this.fillMinutes();this.fillSeconds();this.update();this.showMode();this._attachDatePickerEvents()},show:function(e){this.widget.show();this.height=this.component?this.component.outerHeight():this.$element.outerHeight();this.place();this.$element.trigger({type:"show",date:this._date});this._attachDatePickerGlobalEvents();if(e){e.stopPropagation();e.preventDefault()}},disable:function(){this.$element.find("input").prop("disabled",true);this._detachDatePickerEvents()},enable:function(){this.$element.find("input").prop("disabled",false);this._attachDatePickerEvents()},hide:function(){var collapse=this.widget.find(".collapse");for(var i=0;i<collapse.length;i++){var collapseData=collapse.eq(i).data("collapse");if(collapseData&&collapseData.transitioning)return}this.widget.hide();this.viewMode=this.startViewMode;this.showMode();this.set();this.$element.trigger({type:"hide",date:this._date});this._detachDatePickerGlobalEvents()},set:function(){var formatted="";if(!this._unset)formatted=this.formatDate(this._date);if(!this.isInput){if(this.component){var input=this.$element.find("input");input.val(formatted);this._resetMaskPos(input)}this.$element.data("date",formatted)}else{this.$element.val(formatted);this._resetMaskPos(this.$element)}},setValue:function(newDate){if(!newDate){this._unset=true}else{this._unset=false}if(typeof newDate==="string"){this._date=this.parseDate(newDate)}else if(newDate){this._date=new Date(newDate)}this.set();this.viewDate=UTCDate(this._date.getUTCFullYear(),this._date.getUTCMonth(),1,0,0,0,0);this.fillDate();this.fillTime()},getDate:function(){if(this._unset)return null;return new Date(this._date.valueOf())},setDate:function(date){if(!date)this.setValue(null);else this.setValue(date.valueOf())},setStartDate:function(date){if(date instanceof Date){this.startDate=date}else if(typeof date==="string"){this.startDate=new UTCDate(date);if(!this.startDate.getUTCFullYear()){this.startDate=-Infinity}}else{this.startDate=-Infinity}if(this.viewDate){this.update()}},setEndDate:function(date){if(date instanceof Date){this.endDate=date}else if(typeof date==="string"){this.endDate=new UTCDate(date);if(!this.endDate.getUTCFullYear()){this.endDate=Infinity}}else{this.endDate=Infinity}if(this.viewDate){this.update()}},getLocalDate:function(){if(this._unset)return null;var d=this._date;return new Date(d.getUTCFullYear(),d.getUTCMonth(),d.getUTCDate(),d.getUTCHours(),d.getUTCMinutes(),d.getUTCSeconds(),d.getUTCMilliseconds())},setLocalDate:function(localDate){if(!localDate)this.setValue(null);else this.setValue(Date.UTC(localDate.getFullYear(),localDate.getMonth(),localDate.getDate(),localDate.getHours(),localDate.getMinutes(),localDate.getSeconds(),localDate.getMilliseconds()))},place:function(){var position="absolute";var offset=this.component?this.component.offset():this.$element.offset();this.width=this.component?this.component.outerWidth():this.$element.outerWidth();offset.top=offset.top+this.height;var $window=$(window);if(this.options.width!=undefined){this.widget.width(this.options.width)}if(this.options.orientation=="left"){this.widget.addClass("left-oriented");offset.left=offset.left-this.widget.width()+20}if(this._isInFixed()){position="fixed";offset.top-=$window.scrollTop();offset.left-=$window.scrollLeft()}if($window.width()<offset.left+this.widget.outerWidth()){offset.right=$window.width()-offset.left-this.width;offset.left="auto";this.widget.addClass("pull-right")}else{offset.right="auto";this.widget.removeClass("pull-right")}this.widget.css({position:position,top:offset.top,left:offset.left,right:offset.right})},notifyChange:function(){this.$element.trigger({type:"changeDate",date:this.getDate(),localDate:this.getLocalDate()})},update:function(newDate){var dateStr=newDate;if(!dateStr){if(this.isInput){dateStr=this.$element.val()}else{dateStr=this.$element.find("input").val()}if(dateStr){this._date=this.parseDate(dateStr)}if(!this._date){var tmp=new Date;this._date=UTCDate(tmp.getFullYear(),tmp.getMonth(),tmp.getDate(),tmp.getHours(),tmp.getMinutes(),tmp.getSeconds(),tmp.getMilliseconds())}}this.viewDate=UTCDate(this._date.getUTCFullYear(),this._date.getUTCMonth(),1,0,0,0,0);this.fillDate();this.fillTime()},fillDow:function(){var dowCnt=this.weekStart;var html=$("<tr>");while(dowCnt<this.weekStart+7){html.append('<th class="dow">'+dates[this.language].daysMin[dowCnt++%7]+"</th>")}this.widget.find(".datepicker-days thead").append(html)},fillMonths:function(){var html="";var i=0;while(i<12){html+='<span class="month">'+dates[this.language].monthsShort[i++]+"</span>"}this.widget.find(".datepicker-months td").append(html)},fillDate:function(){var year=this.viewDate.getUTCFullYear();var month=this.viewDate.getUTCMonth();var currentDate=UTCDate(this._date.getUTCFullYear(),this._date.getUTCMonth(),this._date.getUTCDate(),0,0,0,0);var startYear=typeof this.startDate==="object"?this.startDate.getUTCFullYear():-Infinity;var startMonth=typeof this.startDate==="object"?this.startDate.getUTCMonth():-1;var endYear=typeof this.endDate==="object"?this.endDate.getUTCFullYear():Infinity;var endMonth=typeof this.endDate==="object"?this.endDate.getUTCMonth():12;this.widget.find(".datepicker-days").find(".disabled").removeClass("disabled");this.widget.find(".datepicker-months").find(".disabled").removeClass("disabled");this.widget.find(".datepicker-years").find(".disabled").removeClass("disabled");this.widget.find(".datepicker-days th:eq(1)").text(dates[this.language].months[month]+" "+year);var prevMonth=UTCDate(year,month-1,28,0,0,0,0);var day=DPGlobal.getDaysInMonth(prevMonth.getUTCFullYear(),prevMonth.getUTCMonth());prevMonth.setUTCDate(day);prevMonth.setUTCDate(day-(prevMonth.getUTCDay()-this.weekStart+7)%7);if(year==startYear&&month<=startMonth||year<startYear){this.widget.find(".datepicker-days th:eq(0)").addClass("disabled")}if(year==endYear&&month>=endMonth||year>endYear){this.widget.find(".datepicker-days th:eq(2)").addClass("disabled")}var nextMonth=new Date(prevMonth.valueOf());nextMonth.setUTCDate(nextMonth.getUTCDate()+42);nextMonth=nextMonth.valueOf();var html=[];var row;var clsName;while(prevMonth.valueOf()<nextMonth){if(prevMonth.getUTCDay()===this.weekStart){row=$("<tr>");html.push(row)}clsName="";if(prevMonth.getUTCFullYear()<year||prevMonth.getUTCFullYear()==year&&prevMonth.getUTCMonth()<month){clsName+=" old"}else if(prevMonth.getUTCFullYear()>year||prevMonth.getUTCFullYear()==year&&prevMonth.getUTCMonth()>month){clsName+=" new"}if(prevMonth.valueOf()===currentDate.valueOf()){clsName+=" active"}if(prevMonth.valueOf()+864e5<=this.startDate){clsName+=" disabled"}if(prevMonth.valueOf()>this.endDate){clsName+=" disabled"}row.append('<td class="day'+clsName+'">'+prevMonth.getUTCDate()+"</td>");prevMonth.setUTCDate(prevMonth.getUTCDate()+1)}this.widget.find(".datepicker-days tbody").empty().append(html);var currentYear=this._date.getUTCFullYear();var months=this.widget.find(".datepicker-months").find("th:eq(1)").text(year).end().find("span").removeClass("active");if(currentYear===year){months.eq(this._date.getUTCMonth()).addClass("active")}if(currentYear-1<startYear){this.widget.find(".datepicker-months th:eq(0)").addClass("disabled")}if(currentYear+1>endYear){this.widget.find(".datepicker-months th:eq(2)").addClass("disabled")}for(var i=0;i<12;i++){if(year==startYear&&startMonth>i||year<startYear){$(months[i]).addClass("disabled")}else if(year==endYear&&endMonth<i||year>endYear){$(months[i]).addClass("disabled")}}html="";year=parseInt(year/10,10)*10;var yearCont=this.widget.find(".datepicker-years").find("th:eq(1)").text(year+"-"+(year+9)).end().find("td");this.widget.find(".datepicker-years").find("th").removeClass("disabled");if(startYear>year){this.widget.find(".datepicker-years").find("th:eq(0)").addClass("disabled")}if(endYear<year+9){this.widget.find(".datepicker-years").find("th:eq(2)").addClass("disabled")}year-=1;for(var i=-1;i<11;i++){html+='<span class="year'+(i===-1||i===10?" old":"")+(currentYear===year?" active":"")+(year<startYear||year>endYear?" disabled":"")+'">'+year+"</span>";year+=1}yearCont.html(html)},fillHours:function(){var table=this.widget.find(".timepicker .timepicker-hours table");table.parent().hide();var html="";if(this.options.pick12HourFormat){var current=1;for(var i=0;i<3;i+=1){html+="<tr>";for(var j=0;j<4;j+=1){var c=current.toString();html+='<td class="hour">'+padLeft(c,2,"0")+"</td>";current++}html+="</tr>"}}else{var current=0;for(var i=0;i<6;i+=1){html+="<tr>";for(var j=0;j<4;j+=1){var c=current.toString();html+='<td class="hour">'+padLeft(c,2,"0")+"</td>";current++}html+="</tr>"}}table.html(html)},fillMinutes:function(){var table=this.widget.find(".timepicker .timepicker-minutes table");table.parent().hide();var html="";var current=0;for(var i=0;i<5;i++){html+="<tr>";for(var j=0;j<4;j+=1){var c=current.toString();html+='<td class="minute">'+padLeft(c,2,"0")+"</td>";current+=3}html+="</tr>"}table.html(html)},fillSeconds:function(){var table=this.widget.find(".timepicker .timepicker-seconds table");table.parent().hide();var html="";var current=0;for(var i=0;i<5;i++){html+="<tr>";for(var j=0;j<4;j+=1){var c=current.toString();html+='<td class="second">'+padLeft(c,2,"0")+"</td>";current+=3}html+="</tr>"}table.html(html)},fillTime:function(){if(!this._date)return;var timeComponents=this.widget.find(".timepicker span[data-time-component]");var table=timeComponents.closest("table");var is12HourFormat=this.options.pick12HourFormat;var hour=this._date.getUTCHours();var period="AM";if(is12HourFormat){if(hour>=12)period="PM";if(hour===0)hour=12;else if(hour!=12)hour=hour%12;this.widget.find(".timepicker [data-action=togglePeriod]").text(period)}hour=padLeft(hour.toString(),2,"0");var minute=padLeft(this._date.getUTCMinutes().toString(),2,"0");var second=padLeft(this._date.getUTCSeconds().toString(),2,"0");timeComponents.filter("[data-time-component=hours]").text(hour);timeComponents.filter("[data-time-component=minutes]").text(minute);timeComponents.filter("[data-time-component=seconds]").text(second)},click:function(e){e.stopPropagation();e.preventDefault();this._unset=false;var target=$(e.target).closest("span, td, th");if(target.length===1){if(!target.is(".disabled")){switch(target[0].nodeName.toLowerCase()){case"th":switch(target[0].className){case"switch":this.showMode(1);break;case"prev":case"next":var vd=this.viewDate;var navFnc=DPGlobal.modes[this.viewMode].navFnc;var step=DPGlobal.modes[this.viewMode].navStep;if(target[0].className==="prev")step=step*-1;vd["set"+navFnc](vd["get"+navFnc]()+step);this.fillDate();this.set();break}break;case"span":if(target.is(".month")){var month=target.parent().find("span").index(target);this.viewDate.setUTCMonth(month)}else{var year=parseInt(target.text(),10)||0;this.viewDate.setUTCFullYear(year)}if(this.viewMode!==0){this._date=UTCDate(this.viewDate.getUTCFullYear(),this.viewDate.getUTCMonth(),this.viewDate.getUTCDate(),this._date.getUTCHours(),this._date.getUTCMinutes(),this._date.getUTCSeconds(),this._date.getUTCMilliseconds());this.notifyChange()}this.showMode(-1);this.fillDate();this.set();break;case"td":if(target.is(".day")){var day=parseInt(target.text(),10)||1;var month=this.viewDate.getUTCMonth();var year=this.viewDate.getUTCFullYear();if(target.is(".old")){if(month===0){month=11;year-=1}else{month-=1}}else if(target.is(".new")){if(month==11){month=0;year+=1}else{month+=1}}this._date=UTCDate(year,month,day,this._date.getUTCHours(),this._date.getUTCMinutes(),this._date.getUTCSeconds(),this._date.getUTCMilliseconds());this.viewDate=UTCDate(year,month,Math.min(28,day),0,0,0,0);this.fillDate();this.set();this.notifyChange()}break}}}},actions:{incrementHours:function(e){this._date.setUTCHours(this._date.getUTCHours()+1)},incrementMinutes:function(e){this._date.setUTCMinutes(this._date.getUTCMinutes()+1)},incrementSeconds:function(e){this._date.setUTCSeconds(this._date.getUTCSeconds()+1)},decrementHours:function(e){this._date.setUTCHours(this._date.getUTCHours()-1)},decrementMinutes:function(e){this._date.setUTCMinutes(this._date.getUTCMinutes()-1)},decrementSeconds:function(e){this._date.setUTCSeconds(this._date.getUTCSeconds()-1)},togglePeriod:function(e){var hour=this._date.getUTCHours();if(hour>=12)hour-=12;else hour+=12;this._date.setUTCHours(hour)},showPicker:function(){this.widget.find(".timepicker > div:not(.timepicker-picker)").hide();this.widget.find(".timepicker .timepicker-picker").show()},showHours:function(){this.widget.find(".timepicker .timepicker-picker").hide();this.widget.find(".timepicker .timepicker-hours").show()},showMinutes:function(){this.widget.find(".timepicker .timepicker-picker").hide();this.widget.find(".timepicker .timepicker-minutes").show()},showSeconds:function(){this.widget.find(".timepicker .timepicker-picker").hide();this.widget.find(".timepicker .timepicker-seconds").show()},selectHour:function(e){var tgt=$(e.target);var value=parseInt(tgt.text(),10);if(this.options.pick12HourFormat){var current=this._date.getUTCHours();if(current>=12){if(value!=12)value=(value+12)%24}else{if(value===12)value=0;else value=value%12}}this._date.setUTCHours(value);this.actions.showPicker.call(this)},selectMinute:function(e){var tgt=$(e.target);var value=parseInt(tgt.text(),10);this._date.setUTCMinutes(value);this.actions.showPicker.call(this)},selectSecond:function(e){var tgt=$(e.target);var value=parseInt(tgt.text(),10);this._date.setUTCSeconds(value);this.actions.showPicker.call(this)}},doAction:function(e){e.stopPropagation();e.preventDefault();if(!this._date)this._date=UTCDate(1970,0,0,0,0,0,0);var action=$(e.currentTarget).data("action");var rv=this.actions[action].apply(this,arguments);this.set();this.fillTime();this.notifyChange();return rv},stopEvent:function(e){e.stopPropagation();e.preventDefault()},keydown:function(e){var self=this,k=e.which,input=$(e.target);if(k==8||k==46){setTimeout(function(){self._resetMaskPos(input)})}},keypress:function(e){var k=e.which;if(k==8||k==46){return}var input=$(e.target);var c=String.fromCharCode(k);var val=input.val()||"";val+=c;var mask=this._mask[this._maskPos];if(!mask){return false}if(mask.end!=val.length){return}if(!mask.pattern.test(val.slice(mask.start))){val=val.slice(0,val.length-1);while((mask=this._mask[this._maskPos])&&mask.character){val+=mask.character;this._maskPos++}val+=c;if(mask.end!=val.length){input.val(val);return false}else{if(!mask.pattern.test(val.slice(mask.start))){input.val(val.slice(0,mask.start));return false}else{input.val(val);this._maskPos++;return false}}}else{this._maskPos++}},change:function(e){var input=$(e.target);var val=input.val();if(this._formatPattern.test(val)){this.update();this.setValue(this._date.getTime());this.notifyChange();this.set()}else if(val&&val.trim()){this.setValue(this._date.getTime());if(this._date)this.set();else input.val("")}else{if(this._date){this.setValue(null);this.notifyChange();this._unset=true}}this._resetMaskPos(input)},showMode:function(dir){if(dir){this.viewMode=Math.max(this.minViewMode,Math.min(2,this.viewMode+dir))}this.widget.find(".datepicker > div").hide().filter(".datepicker-"+DPGlobal.modes[this.viewMode].clsName).show()},destroy:function(){this._detachDatePickerEvents();this._detachDatePickerGlobalEvents();this.widget.remove();this.$element.removeData("datetimepicker");this.component.removeData("datetimepicker")},formatDate:function(d){return this.format.replace(formatReplacer,function(match){var methodName,property,rv,len=match.length;if(match==="ms")len=1;property=dateFormatComponents[match].property;if(property==="Hours12"){rv=d.getUTCHours();if(rv===0)rv=12;else if(rv!==12)rv=rv%12}else if(property==="Period12"){if(d.getUTCHours()>=12)return"PM";else return"AM"}else{methodName="get"+property;rv=d[methodName]()}if(methodName==="getUTCMonth")rv=rv+1;if(methodName==="getUTCYear")rv=rv+1900-2e3;return padLeft(rv.toString(),len,"0")})},parseDate:function(str){var match,i,property,methodName,value,parsed={};if(!(match=this._formatPattern.exec(str)))return null;for(i=1;i<match.length;i++){property=this._propertiesByIndex[i];if(!property)continue;value=match[i];if(/^\d+$/.test(value))value=parseInt(value,10);parsed[property]=value}return this._finishParsingDate(parsed)},_resetMaskPos:function(input){var val=input.val();for(var i=0;i<this._mask.length;i++){if(this._mask[i].end>val.length){this._maskPos=i;break}else if(this._mask[i].end===val.length){this._maskPos=i+1;break}}},_finishParsingDate:function(parsed){var year,month,date,hours,minutes,seconds,milliseconds;year=parsed.UTCFullYear;if(parsed.UTCYear)year=2e3+parsed.UTCYear;if(!year)year=1970;if(parsed.UTCMonth)month=parsed.UTCMonth-1;else month=0;date=parsed.UTCDate||1;hours=parsed.UTCHours||0;minutes=parsed.UTCMinutes||0;seconds=parsed.UTCSeconds||0;milliseconds=parsed.UTCMilliseconds||0;if(parsed.Hours12){hours=parsed.Hours12}if(parsed.Period12){if(/pm/i.test(parsed.Period12)){if(hours!=12)hours=(hours+12)%24}else{hours=hours%12}}return UTCDate(year,month,date,hours,minutes,seconds,milliseconds)},_compileFormat:function(){var match,component,components=[],mask=[],str=this.format,propertiesByIndex={},i=0,pos=0;while(match=formatComponent.exec(str)){component=match[0];if(component in dateFormatComponents){i++;propertiesByIndex[i]=dateFormatComponents[component].property;components.push("\\s*"+dateFormatComponents[component].getPattern(this)+"\\s*");mask.push({pattern:new RegExp(dateFormatComponents[component].getPattern(this)),property:dateFormatComponents[component].property,start:pos,end:pos+=component.length})}else{components.push(escapeRegExp(component));mask.push({pattern:new RegExp(escapeRegExp(component)),character:component,start:pos,end:++pos})}str=str.slice(component.length)}this._mask=mask;this._maskPos=0;this._formatPattern=new RegExp("^\\s*"+components.join("")+"\\s*$");this._propertiesByIndex=propertiesByIndex},_attachDatePickerEvents:function(){var self=this;this.widget.on("click",".datepicker *",$.proxy(this.click,this));this.widget.on("click","[data-action]",$.proxy(this.doAction,this));this.widget.on("mousedown",$.proxy(this.stopEvent,this));if(this.pickDate&&this.pickTime){this.widget.on("click.togglePicker",".accordion-toggle",function(e){e.stopPropagation();var $this=$(this);var $parent=$this.closest("ul");var expanded=$parent.find(".collapse.in");var closed=$parent.find(".collapse:not(.in)");if(expanded&&expanded.length){var collapseData=expanded.data("collapse");if(collapseData&&collapseData.transitioning)return;expanded.collapse("hide");closed.collapse("show");$this.find("i").toggleClass(self.timeIcon+" "+self.dateIcon);self.$element.find(".add-on i").toggleClass(self.timeIcon+" "+self.dateIcon)}})}if(this.isInput){this.$element.on({focus:$.proxy(this.show,this),change:$.proxy(this.change,this)});if(this.options.maskInput){this.$element.on({keydown:$.proxy(this.keydown,this),keypress:$.proxy(this.keypress,this)})}}else{this.$element.on({change:$.proxy(this.change,this)},"input");if(this.options.maskInput){this.$element.on({keydown:$.proxy(this.keydown,this),keypress:$.proxy(this.keypress,this)},"input")}if(this.component){this.component.on("click",$.proxy(this.show,this))}else{this.$element.on("click",$.proxy(this.show,this))}}},_attachDatePickerGlobalEvents:function(){$(window).on("resize.datetimepicker"+this.id,$.proxy(this.place,this));if(!this.isInput){$(document).on("mousedown.datetimepicker"+this.id,$.proxy(this.hide,this))}},_detachDatePickerEvents:function(){this.widget.off("click",".datepicker *",this.click);this.widget.off("click","[data-action]");this.widget.off("mousedown",this.stopEvent);if(this.pickDate&&this.pickTime){this.widget.off("click.togglePicker")}if(this.isInput){this.$element.off({focus:this.show,change:this.change});if(this.options.maskInput){this.$element.off({keydown:this.keydown,keypress:this.keypress})}}else{this.$element.off({change:this.change},"input");if(this.options.maskInput){this.$element.off({keydown:this.keydown,keypress:this.keypress},"input")}if(this.component){this.component.off("click",this.show)}else{this.$element.off("click",this.show)}}},_detachDatePickerGlobalEvents:function(){$(window).off("resize.datetimepicker"+this.id);if(!this.isInput){$(document).off("mousedown.datetimepicker"+this.id)}},_isInFixed:function(){if(this.$element){var parents=this.$element.parents();var inFixed=false;for(var i=0;i<parents.length;i++){if($(parents[i]).css("position")=="fixed"){inFixed=true;break}}return inFixed}else{return false}}};$.fn.datetimepicker=function(option,val){return this.each(function(){var $this=$(this),data=$this.data("datetimepicker"),options=typeof option==="object"&&option;if(!data){$this.data("datetimepicker",data=new DateTimePicker(this,$.extend({},$.fn.datetimepicker.defaults,options)))}if(typeof option==="string")data[option](val)})};$.fn.datetimepicker.defaults={maskInput:false,pickDate:true,pickTime:true,pick12HourFormat:false,pickSeconds:true,startDate:-Infinity,endDate:Infinity,collapse:true};$.fn.datetimepicker.Constructor=DateTimePicker;var dpgId=0;var dates=$.fn.datetimepicker.dates={en:{days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"],daysShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat","Sun"],daysMin:["Su","Mo","Tu","We","Th","Fr","Sa","Su"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],monthsShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]}};var dateFormatComponents={dd:{property:"UTCDate",getPattern:function(){return"(0?[1-9]|[1-2][0-9]|3[0-1])\\b"}},MM:{property:"UTCMonth",getPattern:function(){return"(0?[1-9]|1[0-2])\\b"}},yy:{property:"UTCYear",getPattern:function(){return"(\\d{2})\\b"}},yyyy:{property:"UTCFullYear",getPattern:function(){return"(\\d{4})\\b"}},hh:{property:"UTCHours",getPattern:function(){return"(0?[0-9]|1[0-9]|2[0-3])\\b"}},mm:{property:"UTCMinutes",getPattern:function(){return"(0?[0-9]|[1-5][0-9])\\b"}},ss:{property:"UTCSeconds",getPattern:function(){return"(0?[0-9]|[1-5][0-9])\\b"}},ms:{property:"UTCMilliseconds",getPattern:function(){return"([0-9]{1,3})\\b"}},HH:{property:"Hours12",getPattern:function(){return"(0?[1-9]|1[0-2])\\b"}},PP:{property:"Period12",getPattern:function(){return"(AM|PM|am|pm|Am|aM|Pm|pM)\\b"}}};var keys=[];for(var k in dateFormatComponents)keys.push(k);keys[keys.length-1]+="\\b";keys.push(".");var formatComponent=new RegExp(keys.join("\\b|"));keys.pop();var formatReplacer=new RegExp(keys.join("\\b|"),"g");function escapeRegExp(str){return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&")}function padLeft(s,l,c){if(l<s.length)return s;else return Array(l-s.length+1).join(c||" ")+s}function getTemplate(timeIcon,pickDate,pickTime,is12Hours,showSeconds,collapse){if(pickDate&&pickTime){return'<div class="bootstrap-datetimepicker-widget dropdown-menu">'+"<ul>"+"<li"+(collapse?' class="collapse in"':"")+">"+'<div class="datepicker">'+DPGlobal.template+"</div>"+"</li>"+'<li class="picker-switch accordion-toggle"><a><i class="'+timeIcon+'"></i></a></li>'+"<li"+(collapse?' class="collapse"':"")+">"+'<div class="timepicker">'+TPGlobal.getTemplate(is12Hours,showSeconds)+"</div>"+"</li>"+"</ul>"+"</div>"}else if(pickTime){return'<div class="bootstrap-datetimepicker-widget dropdown-menu">'+'<div class="timepicker">'+TPGlobal.getTemplate(is12Hours,showSeconds)+"</div>"+"</div>"}else{return'<div class="bootstrap-datetimepicker-widget dropdown-menu">'+'<div class="datepicker">'+DPGlobal.template+"</div>"+"</div>"}}function UTCDate(){return new Date(Date.UTC.apply(Date,arguments))}var DPGlobal={modes:[{clsName:"days",navFnc:"UTCMonth",navStep:1},{clsName:"months",navFnc:"UTCFullYear",navStep:1},{clsName:"years",navFnc:"UTCFullYear",navStep:10}],isLeapYear:function(year){return year%4===0&&year%100!==0||year%400===0},getDaysInMonth:function(year,month){return[31,DPGlobal.isLeapYear(year)?29:28,31,30,31,30,31,31,30,31,30,31][month]},headTemplate:"<thead>"+"<tr>"+'<th class="prev">‹</th>'+'<th colspan="5" class="switch"></th>'+'<th class="next">›</th>'+"</tr>"+"</thead>",contTemplate:'<tbody><tr><td colspan="7"></td></tr></tbody>'};DPGlobal.template='<div class="datepicker-days">'+'<table class="table-condensed">'+DPGlobal.headTemplate+"<tbody></tbody>"+"</table>"+"</div>"+'<div class="datepicker-months">'+'<table class="table-condensed">'+DPGlobal.headTemplate+DPGlobal.contTemplate+"</table>"+"</div>"+'<div class="datepicker-years">'+'<table class="table-condensed">'+DPGlobal.headTemplate+DPGlobal.contTemplate+"</table>"+"</div>";var TPGlobal={hourTemplate:'<span data-action="showHours" data-time-component="hours" class="timepicker-hour"></span>',minuteTemplate:'<span data-action="showMinutes" data-time-component="minutes" class="timepicker-minute"></span>',secondTemplate:'<span data-action="showSeconds" data-time-component="seconds" class="timepicker-second"></span>'};TPGlobal.getTemplate=function(is12Hours,showSeconds){return'<div class="timepicker-picker">'+'<table class="table-condensed"'+(is12Hours?' data-hour-format="12"':"")+">"+"<tr>"+'<td><a href="#" class="btn" data-action="incrementHours"><i class="icon-chevron-up"></i></a></td>'+'<td class="separator"></td>'+'<td><a href="#" class="btn" data-action="incrementMinutes"><i class="icon-chevron-up"></i></a></td>'+(showSeconds?'<td class="separator"></td>'+'<td><a href="#" class="btn" data-action="incrementSeconds"><i class="icon-chevron-up"></i></a></td>':"")+(is12Hours?'<td class="separator"></td>':"")+"</tr>"+"<tr>"+"<td>"+TPGlobal.hourTemplate+"</td> "+'<td class="separator">:</td>'+"<td>"+TPGlobal.minuteTemplate+"</td> "+(showSeconds?'<td class="separator">:</td>'+"<td>"+TPGlobal.secondTemplate+"</td>":"")+(is12Hours?'<td class="separator"></td>'+"<td>"+'<button type="button" class="btn btn-primary" data-action="togglePeriod"></button>'+"</td>":"")+"</tr>"+"<tr>"+'<td><a href="#" class="btn" data-action="decrementHours"><i class="icon-chevron-down"></i></a></td>'+'<td class="separator"></td>'+'<td><a href="#" class="btn" data-action="decrementMinutes"><i class="icon-chevron-down"></i></a></td>'+(showSeconds?'<td class="separator"></td>'+'<td><a href="#" class="btn" data-action="decrementSeconds"><i class="icon-chevron-down"></i></a></td>':"")+(is12Hours?'<td class="separator"></td>':"")+"</tr>"+"</table>"+"</div>"+'<div class="timepicker-hours" data-action="selectHour">'+'<table class="table-condensed">'+"</table>"+"</div>"+'<div class="timepicker-minutes" data-action="selectMinute">'+'<table class="table-condensed">'+"</table>"+"</div>"+(showSeconds?'<div class="timepicker-seconds" data-action="selectSecond">'+'<table class="table-condensed">'+"</table>"+"</div>":"")}})(window.jQuery); \ No newline at end of file Added: trunk/pollen-ui-js/src/main/webapp/js/models/choices.js =================================================================== --- trunk/pollen-ui-js/src/main/webapp/js/models/choices.js (rev 0) +++ trunk/pollen-ui-js/src/main/webapp/js/models/choices.js 2013-06-26 17:50:48 UTC (rev 3840) @@ -0,0 +1,7 @@ +var Choice = can.Model({ + findAll : "GET " + backendUrl + "/polls/{pollId}/choices", + findOne : "GET " + backendUrl + "/polls/{pollId}/choices/{id}", + create : "POST " + backendUrl + "/polls/{pollId}/choices", + update : "PUT " + backendUrl + "/polls/{pollId}/choices/{id}", + destroy : "DELETE " + backendUrl + "/polls/{pollId}/choices/{id}" +},{}); \ No newline at end of file Modified: trunk/pollen-ui-js/src/main/webapp/js/models/comments.js =================================================================== --- trunk/pollen-ui-js/src/main/webapp/js/models/comments.js 2013-06-21 21:26:23 UTC (rev 3839) +++ trunk/pollen-ui-js/src/main/webapp/js/models/comments.js 2013-06-26 17:50:48 UTC (rev 3840) @@ -50,7 +50,7 @@ ]; can.fixture("GET " + backendUrl + "/polls/{pollId}/comments", function(orig) { - return COMMENTS[orig.data.pollId - 1]; + return []; }); var idToInc= 3; Modified: trunk/pollen-ui-js/src/main/webapp/js/models/polls.js =================================================================== --- trunk/pollen-ui-js/src/main/webapp/js/models/polls.js 2013-06-21 21:26:23 UTC (rev 3839) +++ trunk/pollen-ui-js/src/main/webapp/js/models/polls.js 2013-06-26 17:50:48 UTC (rev 3840) @@ -21,20 +21,19 @@ * #L% */ var Poll = can.Model({ - findAll : "GET " + backendUrl + "/polls", - findOne : "GET " + backendUrl + "/polls/{id}", - create : function(attrs) { - var t = paramForWM(attrs, 'poll') + 'userId=' + currentUser.id; - return can.ajax(backendUrl + "/polls",{ - type: "POST", - data: t - }); - }, - update : "PUT " + backendUrl + "/polls/{id}", - destroy : "DELETE " + backendUrl + "/polls/{id}" -},{}); + findAll : "GET " + backendUrl + "/polls/{category}", + findOne : "GET " + backendUrl + "/polls/{id}", + create : function(attrs) { + var t = paramForWM(attrs, 'poll') + 'userId=' + currentUser.id; + return can.ajax(backendUrl + "/polls", { + type: "POST", + data: t + }); + }, + update : "PUT " + backendUrl + "/polls/{id}", + destroy : "DELETE " + backendUrl + "/polls/{id}" +}, {}); -console.log("load polls") var POLLS = [ { id: 1, Modified: trunk/pollen-ui-js/src/main/webapp/js/models/votes.js =================================================================== --- trunk/pollen-ui-js/src/main/webapp/js/models/votes.js 2013-06-21 21:26:23 UTC (rev 3839) +++ trunk/pollen-ui-js/src/main/webapp/js/models/votes.js 2013-06-26 17:50:48 UTC (rev 3840) @@ -148,7 +148,7 @@ ]; can.fixture("GET " + backendUrl + "/polls/{pollId}/votes", function(orig) { - return VOTES[orig.data.pollId - 1]; + return []; }); var idToInc= 3; Added: trunk/pollen-ui-js/src/main/webapp/js/pollen-utils.js =================================================================== --- trunk/pollen-ui-js/src/main/webapp/js/pollen-utils.js (rev 0) +++ trunk/pollen-ui-js/src/main/webapp/js/pollen-utils.js 2013-06-26 17:50:48 UTC (rev 3840) @@ -0,0 +1,13 @@ +var backendUrl = 'http://localhost:8080/pollen/v1'; + +var paramForWM = function(obj, objName) { + var result = ""; + for (var k in obj) { + if (typeof obj[k] === "object") { + result += paramForWM(obj[k], objName + '.' + k); + } else { + result += objName + '.' + k + '=' + obj[k] + '&'; + } + } + return result; +} \ No newline at end of file Modified: trunk/pollen-ui-js/src/main/webapp/views/poll_form.ejs =================================================================== --- trunk/pollen-ui-js/src/main/webapp/views/poll_form.ejs 2013-06-21 21:26:23 UTC (rev 3839) +++ trunk/pollen-ui-js/src/main/webapp/views/poll_form.ejs 2013-06-26 17:50:48 UTC (rev 3840) @@ -1,27 +1,319 @@ <h1><%= pollen.poll.form.create.title %></h1> +<ul class="breadcrumb"> + <li class='active' <%= (el) -> el.data('step', 1) %>><span class='step'>Step 1</span> <span class="divider">/</span></li> + <li <%= (el) -> el.data('step', 2) %>><span class='step'>Step 2</span> <span class="divider">/</span></li> +<li <%= (el) -> el.data('step', 3) %>><span class='step'>Step 3</span> <span class="divider">/</span></li> +</ul> + <form id='pollCreationForm' class="form-horizontal"> - <div class="control-group"> - <label class="control-label" for="pollCreationFormTitle"><%= pollen.poll.title.label %></label> - <div class="controls"> - <input type='text' name='title' id='pollCreationFormTitle' - placeholder='<%= pollen.poll.title.placeholder %>' - value='<%= poll.attr("title")%>'/> + <!-- Basic info step --> + <div class='step1'> + <div class="control-group"> + <label class="control-label" for="pollCreationFormTitle"><%= pollen.poll.title.label %></label> + <div class="controls"> + <input type='text' name='title' id='pollCreationFormTitle' + placeholder='<%= pollen.poll.title.placeholder %>' + value='<%= poll.attr("title")%>' + <%= (el) -> el.data('owner', poll) %>/> + </div> </div> + + <div class="control-group"> + <label class="control-label" for='pollCreationFormDescription'><%= pollen.poll.description.label %></label> + <div class="controls"> + <textarea id='pollCreationFormDescription' + name='description' + placeholder="<%= pollen.poll.description.placeholder %>" + <%= (el) -> el.data('owner', poll) %>><%= poll.attr('description') %></textarea> + </div> + </div> + + <div class="control-group"> + <label class="control-label" for='pollCreationFormCreatorName'><%= pollen.poll.creator.name.label %></label> + <div class="controls"> + <input type='text' name='creator.name' id='pollCreationFormCreatorName' + placeholder='<%= pollen.poll.creator.name.placeholder %>' + value='<%= poll.attr("creator.name")%>' + <%= (el) -> el.data('owner', poll) %>/> + </div> + </div> + + <div class="control-group"> + <label class="control-label" for='pollCreationFormCreatorEmail'><%= pollen.poll.creator.email.label %></label> + <div class="controls"> + <input type='text' name='creator.email' id='pollCreationFormCreatorEmail' + placeholder='<%= pollen.poll.creator.email.placeholder %>' + value='<%= poll.attr("creator.email")%>' + <%= (el) -> el.data('owner', poll) %>/> + </div> + </div> + + <div class="form-actions"> + <button type="button" class="btn btn-primary nextStep"><%= pollen.poll.form.create.button.next %></button> + </div> </div> - <div class="control-group"> - <label class="control-label" for='pollCreationFormDescription'><%= pollen.poll.description.label %></label> - <div class="controls"> - <textarea id='pollCreationFormDescription' - name='description' - placeholder="<%= pollen.poll.description.placeholder %>"><%= poll.attr('description') %></textarea> + <!-- choices step --> + <div class='step2 hide'> + <div class="control-group"> + <label class="control-label" for="pollCreationFormVoteCountingType"><%= pollen.poll.voteCountingType.label %></label> + <div class="controls"> + <select name='voteCountingType' id='pollCreationFormVoteCountingType' <%= (el) -> el.data('owner', poll) %>> + <option value="1" <%= (el) -> el.data('description', 'normal') %>><%= pollen.choice.voteType.normal.label %></option> + <option value="2" <%= (el) -> el.data('description', 'percentage') %>><%= pollen.choice.voteType.percentage.label %></option> + <option value="3" <%= (el) -> el.data('description', 'condorcet') %>><%= pollen.choice.voteType.condorcet.label %></option> + <option value="4" <%= (el) -> el.data('description', 'number') %>><%= pollen.choice.voteType.number.label %></option> + <option value="5" <%= (el) -> el.data('description', 'borda') %>><%= pollen.choice.voteType.borda.label %></option> + <option value="6" <%= (el) -> el.data('description', 'alternative') %>><%= pollen.choice.voteType.alternative.label %></option> + <option value="7" <%= (el) -> el.data('description', 'coombs') %>><%= pollen.choice.voteType.coombs.label %></option> + </select> + <span id='pollCreationFormVoteCountingTypeHelp' class="help-block"><%= pollen.choice.voteType.normal.description %></span> + </div> </div> + + <% choices.each(function(choice) { %> + <div class="control-group controls-row"> + <label class="control-label span1" for='pollCreationFormCreatorName'><%= pollen.poll.choice.name.label %></label> + <div class="controls span2"> + <input type='text' name='name' + placeholder='<%= pollen.poll.choice.name.placeholder %>' + value="<%= choice.attr('name') %>" + <%= (el) -> el.data('owner', choice) %>/> + </div> + + <label class="control-label span1" for='pollCreationFormCreatorName'><%= pollen.poll.choice.description.label %></label> + <div class="controls span3"> + <textarea name='description' class="" + placeholder="<%= pollen.poll.choice.description.placeholder %>" + <%= (el) -> el.data('owner', choice) %>><%= choice.attr('description') %></textarea> + </div> + </div> + <% }) %> + + <div class="form-actions"> + <button type='button' class='btn addChoice'><%= pollen.poll.form.create.button.addChoice %></button> + <button type="button" class="btn btn-primary nextStep"><%= pollen.poll.form.create.button.next %></button> + </div> + </div> - <div class="form-actions"> + <!-- Options step --> + <div class='step3 hide'> + + <!-- dates --> + <fieldset> + <legend><%= pollen.poll.form.create.legend.validityDates %></legend> + + <div class="control-group"> + <label class="control-label" for='pollCreationFormBeginDate'><%= pollen.poll.beginDate.label %></label> + <div class="controls"> + <div class="input-append dateTimePicker"> + <input type="text" name='beginDate' id='pollCreationFormBeginDate' + placeholder='<%= pollen.poll.beginDate.placeholder %>' + value='<%= poll.attr("beginDate") ? moment(poll.attr("beginDate")).format(pollen.common.format.dateTime.moment) : "" %>' + <%= (el) -> el.data('owner', poll) %>/> + <span class="add-on"> + <i data-time-icon="icon-time" data-date-icon="icon-calendar"></i> + </span> + </div> + </div> + </div> + + <div class="control-group"> + <label class="control-label" for='pollCreationFormEndDate'><%= pollen.poll.endDate.label %></label> + <div class="controls"> + <div class="input-append dateTimePicker"> + <input type="text" name='endDate' id='pollCreationFormEndDate' + placeholder='<%= pollen.poll.endDate.placeholder %>' + value='<%= poll.attr("endDate") ? moment(poll.attr("endDate")).format(pollen.common.format.dateTime.moment) : "" %>' + <%= (el) -> el.data('owner', poll) %>/> + <span class="add-on"> + <i data-time-icon="icon-time" data-date-icon="icon-calendar"></i> + </span> + </div> + </div> + </div> + + </fieldset> + + <!-- choices --> + <fieldset> + <legend><%= pollen.poll.form.create.legend.choices %></legend> + + <div class="control-group"> + <div class="controls"> + <label class="checkbox"> + <input type="checkbox" id='pollCreationFormChoiceAddAllowed' name="choiceAddAllowed" + <%= poll.attr('choiceAddAllowed') ? "checked": "" %> + <%= (el) -> el.data('owner', poll) %>/> + <%= pollen.poll.choiceAddAllowed.label %> + </label> + </div> + </div> + + <div class="control-group"> + <label class="control-label" for='pollCreationFormAddChoiceBeginDate'><%= pollen.poll.addChoiceBeginDate.label %></label> + <div class="controls"> + <div class="input-append dateTimePicker addChoiceDate"> + <input type="text" name='addChoiceBeginDate' id='pollCreationFormAddChoiceBeginDate' + placeholder='<%= pollen.poll.addChoiceBeginDate.placeholder %>' + value='<%= poll.attr("addChoiceBeginDate") ? moment(poll.attr("addChoiceBeginDate")).format(pollen.common.format.dateTime.moment) : "" %>' + <%= (el) -> el.data('owner', poll) %>/> + <span class="add-on"> + <i data-time-icon="icon-time" data-date-icon="icon-calendar"></i> + </span> + </div> + </div> + </div> + + <div class="control-group"> + <label class="control-label" for='pollCreationFormAddChoiceEndDate'><%= pollen.poll.addChoiceEndDate.label %></label> + <div class="controls"> + <div class="input-append dateTimePicker addChoiceDate"> + <input type="text" name='addChoiceEndDate' id='pollCreationFormAddChoiceEndDate' + placeholder='<%= pollen.poll.addChoiceEndDate.placeholder %>' + value='<%= poll.attr("addChoiceEndDate") ? moment(poll.attr("addChoiceEndDate")).format(pollen.common.format.dateTime.moment) : "" %>' + <%= (el) -> el.data('owner', poll) %>/> + <span class="add-on"> + <i data-time-icon="icon-time" data-date-icon="icon-calendar"></i> + </span> + </div> + </div> + </div> + + <div class="control-group"> + <label class="control-label" for='pollCreationFormMaxChoiceNumber'><%= pollen.poll.maxChoiceNumber.label %></label> + <div class="controls"> + <input type='number' name='maxChoiceNumber' id='pollCreationFormMaxChoiceNumber' + placeholder='<%= pollen.poll.maxChoiceNumber.placeholder %>' + value='<%= poll.attr("maxChoiceNumber")%>' + <%= (el) -> el.data('owner', poll) %>/> + </div> + </div> + + </fieldset> + + <!-- votes --> + <fieldset> + <legend><%= pollen.poll.form.create.legend.votes %></legend> + + <div class="control-group"> + <label class="control-label" for="pollCreationFormCommentVisibility"><%= pollen.poll.commentVisibility.label %></label> + <div class="controls"> + <select name='commentVisibility' id='pollCreationFormCommentVisibility' <%= (el) -> el.data('owner', poll) %>> + <option value="EVERYBODY"><%= pollen.poll.commentVisibility.everybody.label %></option> + <option value="VOTER"><%= pollen.poll.commentVisibility.voter.label %></option> + <option value="NOBODY"><%= pollen.poll.commentVisibility.nobody.label %></option> + </select> + </div> + </div> + + <div class="control-group"> + <label class="control-label" for="pollCreationFormVoteVisibility"><%= pollen.poll.voteVisibility.label %></label> + <div class="controls"> + <select name='voteVisibility' id='pollCreationFormVoteVisibility' <%= (el) -> el.data('owner', poll) %>> + <option value="EVERYBODY"><%= pollen.poll.voteVisibility.everybody.label %></option> + <option value="VOTER"><%= pollen.poll.voteVisibility.voter.label %></option> + <option value="CREATOR"><%= pollen.poll.voteVisibility.creator.label %></option> + <option value="ANONYMOUS"><%= pollen.poll.voteVisibility.anonymous.label %></option> + </select> + </div> + </div> + + <div class="control-group"> + <div class="controls"> + <label class="checkbox"> + <input type="checkbox" id='pollCreationFormAnonymousVoteAllowed' name="anonymousVoteAllowed" + <%= poll.attr('anonymousVoteAllowed') ? "checked": "" %> + <%= (el) -> el.data('owner', poll) %>/> + <%= pollen.poll.anonymousVoteAllowed.label %> + </label> + </div> + </div> + + <div class="control-group"> + <label class="control-label" for="pollCreationFormPollType"><%= pollen.poll.pollType.label %></label> + <div class="controls"> + <select name='pollType' id='pollCreationFormPollType' <%= (el) -> el.data('owner', poll) %>> + <option value="FREE"><%= pollen.poll.pollType.free.label %></option> + <option value="RESTRICTED"><%= pollen.poll.pollType.restricted.label %></option> + <option value="GROUP"><%= pollen.poll.pollType.group.label %></option> + </select> + </div> + </div> + + </fieldset> + + <!-- results --> + <fieldset> + <legend><%= pollen.poll.form.create.legend.results %></legend> + + <div class="control-group"> + <label class="control-label" for="pollCreationFormResultVisibility"><%= pollen.poll.resultVisibility.label %></label> + <div class="controls"> + <select name='resultVisibility' id='pollCreationFormResultVisibility' <%= (el) -> el.data('owner', poll) %>> + <option value="EVERYBODY"><%= pollen.poll.resultVisibility.everybody.label %></option> + <option value="VOTER"><%= pollen.poll.resultVisibility.voter.label %></option> + <option value="CREATOR"><%= pollen.poll.resultVisibility.creator.label %></option> + </select> + </div> + </div> + + <div class="control-group"> + <div class="controls"> + <label class="checkbox"> + <input type="checkbox" id='pollCreationFormContinuousResults' name="continuousResults" + <%= poll.attr('continuousResults') ? "checked": "" %> + <%= (el) -> el.data('owner', poll) %>/> + <%= pollen.poll.continuousResults.label %> + </label> + </div> + </div> + + </fieldset> + + <!-- notifications --> + <fieldset> + <legend><%= pollen.poll.form.create.legend.notifications %></legend> + + <div class="control-group"> + <label class="control-label" for="pollCreationFormResultVisibility"><%= pollen.poll.resultVisibility.label %></label> + <div class="controls"> + <select name='resultVisibility' id='pollCreationFormResultVisibility' <%= (el) -> el.data('owner', poll) %>> + <option value="EVERYBODY"><%= pollen.poll.resultVisibility.everybody.label %></option> + <option value="VOTER"><%= pollen.poll.resultVisibility.voter.label %></option> + <option value="CREATOR"><%= pollen.poll.resultVisibility.creator.label %></option> + </select> + </div> + </div> + + <div class="control-group"> + <div class="controls"> + <label class="checkbox"> + <input type="checkbox" id='pollCreationFormContinuousResults' name="continuousResults" + <%= poll.attr('continuousResults') ? "checked": "" %> + <%= (el) -> el.data('owner', poll) %>/> + <%= pollen.poll.continuousResults.label %> + </label> + </div> + </div> + + </fieldset> + <div class="form-actions"> <button type='submit' class="btn btn-primary"><%= pollen.poll.form.create.button.save %></button> + </div> </div> -</form> \ No newline at end of file +</form> + +<% + $(function() { + $('.dateTimePicker').datetimepicker({ + language: 'fr_FR', + pickSeconds: false, + format: pollen.common.format.dateTime.input + }); + }); +%> \ No newline at end of file Modified: trunk/pollen-ui-js/src/main/webapp/views/vote.ejs =================================================================== --- trunk/pollen-ui-js/src/main/webapp/views/vote.ejs 2013-06-21 21:26:23 UTC (rev 3839) +++ trunk/pollen-ui-js/src/main/webapp/views/vote.ejs 2013-06-26 17:50:48 UTC (rev 3840) @@ -3,18 +3,18 @@ <h1><%= poll.attr('title') %></h1> <p> - <%= pollen.vote.poll.author(poll.attr('creatorName')) %> + <%= pollen.vote.poll.author(poll.attr('creator.name')) %> <!-- number of votes --> | <a id="voteSummary" class='link'><i class='icon-user'></i> <%= votes.attr('length') %></a> <!-- number of comments--> | <a id="commentSummary" class='link'><i class='icon-comment'></i> <%= comments.attr('length') %></a> <!-- poll dates --> <% if (poll.attr('beginDate') && poll.attr('endDate')) { %> - | <i class='icon-time'></i> <%= pollen.common.date.fromTo(moment(poll.attr('beginDate')).format(pollen.common.format.date), moment(poll.attr('endDate')).format(pollen.common.format.date)) %> + | <i class='icon-time'></i> <%= pollen.common.date.fromTo(moment(poll.attr('beginDate')).format(pollen.common.format.dateTime.moment), moment(poll.attr('endDate')).format(pollen.common.format.dateTime.moment)) %> <% } else if (poll.attr('beginDate')) { %> - | <i class='icon-time'></i> <%= pollen.common.date.from(moment(poll.attr('beginDate')).format(pollen.common.format.date)) %> + | <i class='icon-time'></i> <%= pollen.common.date.from(moment(poll.attr('beginDate')).format(pollen.common.format.dateTime.moment)) %> <% } else if (poll.attr('endDate')) { %> - | <i class='icon-time'></i> <%= pollen.common.date.to(moment(poll.attr('endDate')).format(pollen.common.format.date)) %> + | <i class='icon-time'></i> <%= pollen.common.date.to(moment(poll.attr('endDate')).format(pollen.common.format.dateTime.moment)) %> <% } %> </p> @@ -36,8 +36,9 @@ <h3><%= pollen.vote.choices.list.title %></h3> <ol> - <% poll.choices.each(function(choice) { %> - <li><strong><%= choice.attr('name') %></strong> : <%= choice.attr('description') %></li> + <% choices.each(function(choice) { %> + <li><strong><%= choice.attr('name') %></strong> : + <%== choice.attr('description') ? choice.attr('description') : "<em>" + pollen.choice.noDescription + "</em>" %></li> <% }); %> </ol> <% var now = moment().valueOf(); @@ -80,7 +81,7 @@ <thead> <tr> <th><%= pollen.vote.votes.list.header.voter %></th> - <% poll.choices.each(function(choice, i) { %> + <% choices.each(function(choice, i) { %> <th data-container='body' data-placement='top' title='<%= choice.attr("description") %>'> <%= choice.attr('name') %> </th> @@ -92,7 +93,7 @@ <tr> <td><%= vote.attr('voterListMember.name') %></td> <% - poll.choices.each(function(choice) { + choices.each(function(choice) { var voteChoice = vote.voteToChoices[choice.id]; if (voteChoice == null) { %> @@ -110,7 +111,7 @@ <tr> <td>Resultats</td> - <% poll.choices.each(function(choice) { %> + <% choices.each(function(choice) { %> <td class='result'> <%= poll.results.attr(choice.id) %> </td> @@ -130,7 +131,7 @@ </div> </div> </td> - <%poll.choices.each(function(choice, i) { %> + <% choices.each(function(choice, i) { %> <td><input name="<%= i %>" type='checkbox'/></td> <% }); %> </tr> @@ -182,7 +183,7 @@ <%= comment.attr('text') %> </p> <div class='footer'> - <small><%= comment.attr('author') %> | <%= moment(comment.attr('postDate')).format(pollen.common.format.dateTime) %></small> + <small><%= comment.attr('author') %> | <%= moment(comment.attr('postDate')).format(pollen.common.format.dateTime.moment) %></small> </div> </div>