This is an automated email from the git hooks/post-receive script. New commit to branch develop in repository pollen. See https://gitlab.nuiton.org/chorem/pollen.git commit 2c976907302e83eadfa66a49cbced76eb3f987ae Author: Sylvain Bavencoff <bavencoff@codelutin.com> Date: Wed Mar 29 09:45:05 2017 +0200 écran du profil utilisateur --- .../org/chorem/pollen/rest/api/v1/AuthApi.java | 4 +- pollen-rest-api/src/main/resources/mapping | 2 +- .../pollen/services/service/PollenUserService.java | 2 +- pollen-ui-riot-js/src/main/web/css/main.css | 18 +- pollen-ui-riot-js/src/main/web/i18n.json | 38 ++++ pollen-ui-riot-js/src/main/web/js/AuthService.js | 2 +- pollen-ui-riot-js/src/main/web/js/Session.js | 4 + pollen-ui-riot-js/src/main/web/js/UserService.js | 5 + pollen-ui-riot-js/src/main/web/tag/Pollen.tag.html | 5 +- .../src/main/web/tag/SignCheck.tag.html | 2 +- pollen-ui-riot-js/src/main/web/tag/SignUp.tag.html | 4 +- .../src/main/web/tag/UserProfile.tag.html | 213 +++++++++++++++++++++ .../src/main/web/tag/poll/Voters.tag.html | 2 +- 13 files changed, 285 insertions(+), 16 deletions(-) diff --git a/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/AuthApi.java b/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/AuthApi.java index 604daf9..1c50606 100644 --- a/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/AuthApi.java +++ b/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/AuthApi.java @@ -148,9 +148,9 @@ public class AuthApi extends WebMotionController { } - public void resendValidation(PollenUserService pollenUserService, String login, PollenUIContext pollenUiContext) { + public void resendValidation(PollenUserService pollenUserService, String login, PollenUIContext pollenUIContext) { - pollenUserService.resendValidation(login, pollenUiContext); + pollenUserService.resendValidation(login, pollenUIContext); } diff --git a/pollen-rest-api/src/main/resources/mapping b/pollen-rest-api/src/main/resources/mapping index e838a4b..aacf80e 100644 --- a/pollen-rest-api/src/main/resources/mapping +++ b/pollen-rest-api/src/main/resources/mapping @@ -57,7 +57,7 @@ POST,PUT /v1/login AuthApi.login POST,PUT /v1/login2 AuthApi.login2 GET /v1/lostpassword/{login} AuthApi.lostPassword GET /v1/logout AuthApi.logout -GET /v1/resendValidation/{login} AuthApi.resendValidation +POST,PUT /v1/resendValidation AuthApi.resendValidation # ChoiceApi diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/service/PollenUserService.java b/pollen-services/src/main/java/org/chorem/pollen/services/service/PollenUserService.java index 861a09d..ec36fb9 100644 --- a/pollen-services/src/main/java/org/chorem/pollen/services/service/PollenUserService.java +++ b/pollen-services/src/main/java/org/chorem/pollen/services/service/PollenUserService.java @@ -219,7 +219,7 @@ public class PollenUserService extends PollenServiceSupport implements PollenSer try { getSecurityService().checkUserPassword(user, oldPassword); } catch (PollenInvalidPasswordException e) { - check(errorMap, "password", false, l(getLocale(), "pollen.error.user.passwordInvalid")); + check(errorMap, "oldPassword", false, l(getLocale(), "pollen.error.user.passwordInvalid")); } } diff --git a/pollen-ui-riot-js/src/main/web/css/main.css b/pollen-ui-riot-js/src/main/web/css/main.css index 3f0fb9e..020b9cc 100644 --- a/pollen-ui-riot-js/src/main/web/css/main.css +++ b/pollen-ui-riot-js/src/main/web/css/main.css @@ -57,7 +57,7 @@ input, textarea { } .body-content { - flex-grow: 1; + flex-grow: 1; overflow: hidden; } @@ -103,23 +103,31 @@ form .actions { justify-content: space-between; } -form .actions .c-button { +form .actions .c-button, +form .actions-left .c-button, +form .actions-right .c-button { margin: 2px; - } -form .actions .actions-left { +form .actions-left { + padding: 5px 0; display: flex; justify-content: flex-start; flex-wrap: wrap-reverse; } -form .actions .actions-right { +form .actions-right { + padding: 5px 0; display: flex; justify-content: flex-end; flex-wrap: wrap; } +form .actions .actions-left, +form .actions .actions-right { + padding: 0; +} + a.c-button, input.c-button, button.c-button { diff --git a/pollen-ui-riot-js/src/main/web/i18n.json b/pollen-ui-riot-js/src/main/web/i18n.json index ad31bbc..5d371d2 100644 --- a/pollen-ui-riot-js/src/main/web/i18n.json +++ b/pollen-ui-riot-js/src/main/web/i18n.json @@ -252,6 +252,25 @@ "user_email": "Courriel", "user_cancel": "Annuler", "user_save": "Enregistrer", + "userProfile_title": "Mon profil", + "userProfile_identity": "Identité", + "userProfile_name": "Nom", + "userProfile_name_placeholder": "Entrez votre nom d'utilisateur", + "userProfile_email": "Courriel", + "userProfile_email_placeholder": "Entrez votre courriel", + "userProfile_emailValidate": "Vérifier", + "userProfile_emailValidationWaiting": "En cours de validation", + "userProfile_resendValidation": "Envoyer une nouvelle invitation", + "userProfile_saveIdentity": "Enregistrer", + "userProfile_passwordChange": "Changement de mot de passe", + "userProfile_oldPassword": "Ancien mot de passe", + "userProfile_oldPassword_placeholder": "Entrez votre ancien mot de passe", + "userProfile_newPassword": "Nouveau mot de passe", + "userProfile_newPassword_placeholder": "Entrez votre nouveau mot de passe", + "userProfile_repeatPassword": "Confirmation du mot de passe", + "userProfile_repeatPassword_placeholder": "Répétez votre mot de passe", + "userProfile_repeatPassword_error": "Les deux mots de passe ne sont pas identiques.", + "userProfile_savePassword": "Enregistrer", "choice_description_placeholder": "Vous pouvez saisir une description", "date-picker_today": "Aujourd'hui", "choice_text": "Renseignez un text", @@ -506,6 +525,25 @@ "user_email": "Email", "user_cancel": "Cancel", "user_save": "Save", + "userProfile_title": "My profile", + "userProfile_identity": "Identity", + "userProfile_name": "Name", + "userProfile_name_placeholder": "Entrer your user name", + "userProfile_email": "Email", + "userProfile_email_placeholder": "Enter your email", + "userProfile_emailValidate": "Validate", + "userProfile_emailValidationWaiting": "Validation wainting", + "userProfile_resendValidation": "Send a new invitation", + "userProfile_saveIdentity": "Save", + "userProfile_passwordChange": "Password change", + "userProfile_oldPassword": "Old password", + "userProfile_oldPassword_placeholder": "Enter your old password", + "userProfile_newPassword": "New password", + "userProfile_newPassword_placeholder": "Enter your new password", + "userProfile_repeatPassword": "New password confirmation", + "userProfile_repeatPassword_placeholder": "Confirm your new password", + "userProfile_repeatPassword_error": "The two passwords are not identical.", + "userProfile_savePassword": "Save", "choice_description_placeholder": "You can enter a description", "date-picker_today": "Today", "choice_text": "Set a text", diff --git a/pollen-ui-riot-js/src/main/web/js/AuthService.js b/pollen-ui-riot-js/src/main/web/js/AuthService.js index b1d9368..7238ed5 100644 --- a/pollen-ui-riot-js/src/main/web/js/AuthService.js +++ b/pollen-ui-riot-js/src/main/web/js/AuthService.js @@ -62,7 +62,7 @@ class AuthService extends FetchService { } resendValidation(email) { - return this.get("/v1/resendValidation/" + email); + return this.form("/v1/resendValidation", {login: email}); } } diff --git a/pollen-ui-riot-js/src/main/web/js/Session.js b/pollen-ui-riot-js/src/main/web/js/Session.js index 5a4414f..8420a0b 100644 --- a/pollen-ui-riot-js/src/main/web/js/Session.js +++ b/pollen-ui-riot-js/src/main/web/js/Session.js @@ -75,6 +75,10 @@ class Session { } start() { + this.updateUser(); + } + + updateUser() { if (this.isConnected()) { this.connect().then(user => { this.user = user; diff --git a/pollen-ui-riot-js/src/main/web/js/UserService.js b/pollen-ui-riot-js/src/main/web/js/UserService.js index a3b0f20..6ed3f3c 100644 --- a/pollen-ui-riot-js/src/main/web/js/UserService.js +++ b/pollen-ui-riot-js/src/main/web/js/UserService.js @@ -59,6 +59,11 @@ class UserService extends FetchService { return this.form("/v1/users/edit", {user: user}); } + changePassword(userId, oldPassword, newPassword) { + let body = {oldPassword: oldPassword, newPassword: newPassword}; + return this.form("/v1/users/" + userId + "/password", body); + } + } module.exports = singleton(UserService); diff --git a/pollen-ui-riot-js/src/main/web/tag/Pollen.tag.html b/pollen-ui-riot-js/src/main/web/tag/Pollen.tag.html index 14a6de4..ca4e7a7 100644 --- a/pollen-ui-riot-js/src/main/web/tag/Pollen.tag.html +++ b/pollen-ui-riot-js/src/main/web/tag/Pollen.tag.html @@ -29,6 +29,7 @@ require("./poll/EditPoll.tag.html"); require("./poll/Poll.tag.html"); require("./poll/Polls.tag.html"); require("./Users.tag.html"); +require("./UserProfile.tag.html"); <Pollen class="body-wrapper"> <PollenHeader/> <PollenWaiter parent-id="body-content"/> @@ -58,8 +59,8 @@ require("./Users.tag.html"); route("/signup/validate", () => { riot.mount(this.refs.content, "signup", {validate: true}); }); - route("/signcheck/*/*", (id, token) => { - riot.mount(this.refs.content, "signcheck", {id: id, token: token}); + route("/signcheck/*/*", (userId, token) => { + riot.mount(this.refs.content, "signcheck", {userId: userId, token: token}); }); route("/poll/created", () => { diff --git a/pollen-ui-riot-js/src/main/web/tag/SignCheck.tag.html b/pollen-ui-riot-js/src/main/web/tag/SignCheck.tag.html index 4d2dd70..e8f001a 100644 --- a/pollen-ui-riot-js/src/main/web/tag/SignCheck.tag.html +++ b/pollen-ui-riot-js/src/main/web/tag/SignCheck.tag.html @@ -55,7 +55,7 @@ this.waiting = true; this.error = false; this.succes = false; - authService.validateEmail(this.opts.id, this.opts.token) + authService.validateEmail(this.opts.userId, this.opts.token) .then(() => { this.waiting = false; this.succes = true; diff --git a/pollen-ui-riot-js/src/main/web/tag/SignUp.tag.html b/pollen-ui-riot-js/src/main/web/tag/SignUp.tag.html index 0f18966..049b672 100644 --- a/pollen-ui-riot-js/src/main/web/tag/SignUp.tag.html +++ b/pollen-ui-riot-js/src/main/web/tag/SignUp.tag.html @@ -88,9 +88,9 @@ require("./popup/AccountCreated.tag.html"); <a class="resend-validation" onclick="{resendValidation}">{__.resendValidation}</a> - <div class="actions"> + <div class="actions-right"> <button type="submit" - class="c-button c-button--info pull-right"> + class="c-button c-button--info"> <i class="fa fa-plus" aria-hidden="true"></i> {__.validate} </button> diff --git a/pollen-ui-riot-js/src/main/web/tag/UserProfile.tag.html b/pollen-ui-riot-js/src/main/web/tag/UserProfile.tag.html new file mode 100644 index 0000000..30c5a7a --- /dev/null +++ b/pollen-ui-riot-js/src/main/web/tag/UserProfile.tag.html @@ -0,0 +1,213 @@ +<UserProfile> + + <div class="container"> + <h1 class="c-heading"><i class="fa fa-user"/> {__.title}</h1> + <hr> + <form ref="identity-form" class="identity-form" onsubmit="{submitIdentity}"> + <h3 class="c-heading"><i class="fa fa-address-card"/> {__.identity}</h3> + <div class="o-form-element"> + <label class="c-label" for="name">{__.name}</label> + <input class="c-field {c-field--error : errors.name}" + type="text" + name="name" + ref="name" + value={user.name} + placeholder="{__.name_placeholder}" + required> + <div if="{errors.name}" + class="c-hint--static c-hint--error"> + {errors.name} + </div> + </div> + + <div class="o-form-element"> + <label class="c-label" for="email">{__.email}</label> + <div class="o-field o-field--icon-right"> + <input class="c-field {c-field--error : errors.email}" + type="email" + name="email" + ref="email" + value={user.email} + placeholder="{__.email_placeholder}" + required> + <i class="fa fa-fw fa-{user.emailIsValidate ? 'check' : 'refresh'} c-icon" + title={user.emailIsValidate ? __.emailValidate : __.emailValidationWaiting}></i> + </div> + <div if="{errors.email}" + class="c-hint--static c-hint--error"> + {errors.email} + </div> + </div> + + <div class="actions-right"> + <button type="button" + class="c-button c-button--gost-info" + if={!user.emailIsValidate} + onclick={resendValidation}> + <i class="fa fa-paper-plane" aria-hidden="true"></i> + {__.resendValidation} + </button> + <button type="submit" + class="c-button c-button--info"> + <i class="fa fa-check" aria-hidden="true"></i> + {__.saveIdentity} + </button> + </div> + </form> + <hr> + <form ref="password-form" class="password-form" onsubmit="{submitPassword}"> + <h3 class="c-heading"><i class="fa fa-key"/> {__.passwordChange}</h3> + <div class="o-form-element"> + <label class="c-label" for="oldPassword">{__.oldPassword}</label> + <input class="c-field {c-field--error : errors.oldPassword}" + type="password" + name="oldPassword" + ref="oldPassword" + placeholder="{__.oldPassword_placeholder}" + required> + <div if="{errors.oldPassword}" + class="c-hint--static c-hint--error"> + {errors.oldPassword} + </div> + </div> + + <div class="o-form-element"> + <label class="c-label" for="newPassword">{__.newPassword}</label> + <input class="c-field {c-field--error : errors.newPassword}" + type="password" + name="newPassword" + ref="newPassword" + placeholder="{__.newPassword_placeholder}" + onblur="{checkNewPassword}" + required> + <div if="{errors.newPassword}" + class="c-hint--static c-hint--error"> + {errors.newPassword} + </div> + </div> + + <div class="o-form-element"> + <label class="c-label" for="email">{__.repeatPassword}</label> + <input class="c-field {c-field--error : errors.repeatPassword}" + type="password" + name="repeatPassword" + ref="repeatPassword" + placeholder="{__.repeatPassword_placeholder}" + onblur="{checkPassword}" + onkeypress="{clearPasswordError}" + required> + <div if="{errors.repeatPassword}" + class="c-hint--static c-hint--error"> + {errors.repeatPassword} + </div> + </div> + + <div class="actions-right"> + <button type="submit" + class="c-button c-button--info"> + <i class="fa fa-check" aria-hidden="true"></i> + {__.savePassword} + </button> + </div> + </form> + </div> + + <script type="es6"> + this.loaded = false; + let session = require("../js/Session"); + this.installBundle(session, "userProfile"); + this.errors = {}; + this.user = session.getUser() || {}; + let userService = require("../js/UserService"); + let authService = require("../js/AuthService"); + + this.onUserChange = (user) => { + this.user = user || {}; + this.update(); + }; + + this.resendValidation = () => { + authService.resendValidation(this.user.email); + }; + + this.submitIdentity = e => { + e.preventDefault(); + e.stopPropagation(); + this.user.name = this.refs.name.value; + this.user.email = this.refs.email.value; + userService.saveUser(this.user).then(() => { + session.updateUser(); + }); + }; + + this.checkPassword = () => { + var password = this.refs.newPassword.value; + var repeatPassword = this.refs.repeatPassword.value; + + if (repeatPassword && password !== repeatPassword) { + this.errors.repeatPassword = this._l("repeatPassword_error"); + } else { + delete this.errors.repeatPassword; + } + }; + + this.submitPassword = (e) => { + e.preventDefault(); + e.stopPropagation(); + + this.errors = {}; + + this.checkPassword(); + if (this.errors.repeatPassword === undefined) { + let oldPassword = this.refs.oldPassword.value; + let newPassword = this.refs.newPassword.value; + userService.changePassword(this.user.id, oldPassword, newPassword).then(() => { + this.refs.oldPassword.value = ""; + this.refs.newPassword.value = ""; + this.refs.repeatPassword.value = ""; + this.update(); + }) + .catch((errors) => { + this.errors = errors; + this.update(); + }); + } + }; + + this.bus.on("user", this.onUserChange); + + this.on("before-unmount", () => { + this.bus.off("user", this.onUserChange); + }); + + + </script> + + <style> + h1.c-heading { + text-align: center; + } + + @media (min-width: 640px) { + .o-form-element .c-label:first-child { + width: 25%; + display: inline-block; + text-align: right; + float: left; + padding-top: 0.5em; + padding-right: 5px; + } + + .o-form-element .c-field { + width: 75%; + display: inline-block; + } + + .o-form-element .c-hint--static { + margin-left: 25%; + } + } + + </style> + +</UserProfile> diff --git a/pollen-ui-riot-js/src/main/web/tag/poll/Voters.tag.html b/pollen-ui-riot-js/src/main/web/tag/poll/Voters.tag.html index e55e159..bdce5c8 100644 --- a/pollen-ui-riot-js/src/main/web/tag/poll/Voters.tag.html +++ b/pollen-ui-riot-js/src/main/web/tag/poll/Voters.tag.html @@ -70,7 +70,7 @@ this.submit = () => { this.form.model.pollType = this.refs.pollType.value; this.form.model.withMe = this.refs.withMe.checked; - this.form.model.participants = this.refs.participants.value ? this.refs.participants.value.split("/s") : []; + this.form.model.participants = this.refs.participants.value ? this.refs.participants.value.split(/\s+/) : []; }; </script> -- To stop receiving notification emails like this one, please contact chorem.org SCM administrator <admin+scm@chorem.org>.