branch develop updated (6f6e3b9 -> 85886fb)
This is an automated email from the git hooks/post-receive script. New change to branch develop in repository pollen. See https://gitlab.nuiton.org/chorem/pollen.git from 6f6e3b9 Ajout d'une attente pendant les requêtes Rest new 85886fb écrans d'administration des sondages et des utilisateurs The 1 revisions listed above as "new" are entirely new to this repository and will be described in separate emails. The revisions listed as "adds" were already present in the repository and have only been added to this reference. Detailed log of new commits: commit 85886fb91608659cd362b2991d1d531fe5479a3e Author: Sylvain Bavencoff <bavencoff@codelutin.com> Date: Mon Mar 27 18:02:29 2017 +0200 écrans d'administration des sondages et des utilisateurs Summary of changes: .../pollen/services/service/PollenUserService.java | 18 +- pollen-ui-riot-js/src/main/web/i18n.json | 56 ++-- pollen-ui-riot-js/src/main/web/js/UserService.js | 4 + pollen-ui-riot-js/src/main/web/tag/Pollen.tag.html | 10 +- .../src/main/web/tag/PollenHeader.tag.html | 5 + .../src/main/web/tag/UserCard.tag.html | 168 +++++++++++ pollen-ui-riot-js/src/main/web/tag/Users.tag.html | 336 ++++----------------- 7 files changed, 277 insertions(+), 320 deletions(-) create mode 100644 pollen-ui-riot-js/src/main/web/tag/UserCard.tag.html -- To stop receiving notification emails like this one, please contact chorem.org SCM administrator <admin+scm@chorem.org>.
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 85886fb91608659cd362b2991d1d531fe5479a3e Author: Sylvain Bavencoff <bavencoff@codelutin.com> Date: Mon Mar 27 18:02:29 2017 +0200 écrans d'administration des sondages et des utilisateurs --- .../pollen/services/service/PollenUserService.java | 18 +- pollen-ui-riot-js/src/main/web/i18n.json | 56 ++-- pollen-ui-riot-js/src/main/web/js/UserService.js | 4 + pollen-ui-riot-js/src/main/web/tag/Pollen.tag.html | 10 +- .../src/main/web/tag/PollenHeader.tag.html | 5 + .../src/main/web/tag/UserCard.tag.html | 168 +++++++++++ pollen-ui-riot-js/src/main/web/tag/Users.tag.html | 336 ++++----------------- 7 files changed, 277 insertions(+), 320 deletions(-) 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 cdb6fde..861a09d 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 @@ -353,22 +353,8 @@ public class PollenUserService extends PollenServiceSupport implements PollenSer } - boolean passwordNotBlank = checkNotBlank(errors, "password", user.getPassword(), l(getLocale(), "pollen.error.user.passwordEmpty")); - - if (userExists && passwordNotBlank) { - - // check current password - - try { - - getSecurityService().checkUserPassword(persisted, user.getPassword()); - - } catch (PollenInvalidPasswordException e) { - - check(errors, "password", false, l(getLocale(), "pollen.error.user.passwordInvalid")); - - } - + if (!userExists) { + checkNotBlank(errors, "password", user.getPassword(), l(getLocale(), "pollen.error.user.passwordEmpty")); } return errors; diff --git a/pollen-ui-riot-js/src/main/web/i18n.json b/pollen-ui-riot-js/src/main/web/i18n.json index 5f55e30..ad31bbc 100644 --- a/pollen-ui-riot-js/src/main/web/i18n.json +++ b/pollen-ui-riot-js/src/main/web/i18n.json @@ -235,21 +235,23 @@ "poll_created_vote": "Pour voter, veuillez utiliser le lien suivant", "poll_created_editUrl": "Gérer le sondage", "poll_created_voteUrl": "Voter", + "users_title": "Les utilisateurs", + "users_sort": "Trier par", "users_name": "Nom", "users_email": "Courriel", - "users_administrator": "Administrateur", - "users_status": "Statut", - "users_title": "Les utilisateurs", - "users_actions": "Actions", - "users_makeAdmin": "Rendre administrateur", - "users_unmakeAdmin": "Ne plus être administrateur", - "users_banUser": "Désactiver l'utilisateur", - "users_deleteUser": "Supprimer l'utilisateur", - "users_deleteUserMessage": "Supprimer l'utilisateur ?", - "users_CREATED": "En cours d'utilisation", - "users_VALIDATION": "En cours de validation", - "users_DISABLED": "Désactivé", - "users_BANNED": "Banni", + "users_noUser": "Aucun utilisateur", + "user_banned": "Banni", + "user_emailValidate": "En cours de validation", + "user_administrator": "Administrateur", + "user_edit": "Modifier l'utilisateur", + "user_banUser": "Désactiver l'utilisateur", + "user_banUserMessage": "Désactiver l'utilisateur ?", + "user_deleteUser": "Supprimer l'utilisateur", + "user_deleteUserMessage": "Supprimer l'utilisateur ?", + "user_name": "Nom", + "user_email": "Courriel", + "user_cancel": "Annuler", + "user_save": "Enregistrer", "choice_description_placeholder": "Vous pouvez saisir une description", "date-picker_today": "Aujourd'hui", "choice_text": "Renseignez un text", @@ -487,21 +489,23 @@ "poll_created_vote": "To vote on poll, please use following link", "poll_created_editUrl": "Manage poll", "poll_created_voteUrl": "Vote on poll", + "users_title": "All users", + "users_sort": "Sort by", "users_name": "Name", "users_email": "Email", - "users_administrator": "Administrator", - "users_status": "Status", - "users_title": "All users", - "users_actions": "Actions", - "users_makeAdmin": "Make administrator", - "users_unmakeAdmin": "Remove administrator", - "users_banUser": "Ban user", - "users_deleteUser": "Delete user", - "users_deleteUserMessage": "Delete user?", - "users_CREATED": "Account in use", - "users_VALIDATION": "Account validation", - "users_DISABLED": "Account disabled", - "users_BANNED": "Account banned", + "users_noUser": "No user", + "user_banned": "banned", + "user_emailValidate": "email validation waiting", + "user_administrator": "Administrator", + "user_edit": "Edit user", + "user_banUser": "Ban user", + "user_banUserMessage": "Ban user ?", + "user_deleteUser": "Delete user", + "user_deleteUserMessage": "Delete user ?", + "user_name": "Name", + "user_email": "Email", + "user_cancel": "Cancel", + "user_save": "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/UserService.js b/pollen-ui-riot-js/src/main/web/js/UserService.js index 4fdf53d..a3b0f20 100644 --- a/pollen-ui-riot-js/src/main/web/js/UserService.js +++ b/pollen-ui-riot-js/src/main/web/js/UserService.js @@ -55,6 +55,10 @@ class UserService extends FetchService { return this.doDelete(url); } + saveUser(user) { + return this.form("/v1/users/edit", {user: user}); + } + } 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 5df1484..14a6de4 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 @@ -87,19 +87,17 @@ require("./Users.tag.html"); }); route("/poll", () => { - if (!session.isConnected()) { + if (!session.isConnected() && !session.getUser.administrator) { route("/signin?url=/poll"); } else { - riot.mount(this.refs.content, "polls", {method: "polls", session: session}); } }); route("/user", () => { - if (!session.isConnected()) { + if (!session.isConnected() && !session.getUser.administrator) { route("/signin?url=/user"); } else { - riot.mount(this.refs.content, "users", {session: session}); } }); @@ -159,5 +157,9 @@ require("./Users.tag.html"); riot.mount(this.refs.content, "home"); }); + this.bus.on("unauthorize", () => { + route("signin?url=" + window.location.hash.substring(1)); + }); + </script> </Pollen> diff --git a/pollen-ui-riot-js/src/main/web/tag/PollenHeader.tag.html b/pollen-ui-riot-js/src/main/web/tag/PollenHeader.tag.html index 9d1f942..8f33ccb 100644 --- a/pollen-ui-riot-js/src/main/web/tag/PollenHeader.tag.html +++ b/pollen-ui-riot-js/src/main/web/tag/PollenHeader.tag.html @@ -57,6 +57,11 @@ require("./HeaderI18n.tag.html"); <a href="#user/favoriteLists">{__.myFavoriteLists}</a> <span role="separator" class="divider"></span> <a onclick="{signOut}">{__.signout}</a> + <virtual if="{user.administrator}"> + <span role="separator" class="divider"></span> + <a href="#user">{__.users}</a> + <a href="#poll">{__.polls}</a> + </virtual> </virtual> </div> </div> diff --git a/pollen-ui-riot-js/src/main/web/tag/UserCard.tag.html b/pollen-ui-riot-js/src/main/web/tag/UserCard.tag.html new file mode 100644 index 0000000..6931865 --- /dev/null +++ b/pollen-ui-riot-js/src/main/web/tag/UserCard.tag.html @@ -0,0 +1,168 @@ +<UserCard> + <div class="user-card-view" if={!editing}> + <div class="login"> + <span> + <i class="fa fa-ban" if={user.isBanned} title={__.banned}></i> + <i class="fa fa-cog" if={user.administrator} title={__.administrator}></i> + {opts.user.name} - {opts.user.email} + <i class="fa fa-refresh" if={!user.emailIsValidate} title={__.emailValidate}></i> + </span> + </div> + + <div class="flags"> + + </div> + + <div class="actions"> + <i class="fa fa-pencil-square-o" + title={__.edit} + onclick={startEdition}></i> + <i class="fa fa-ban" + if={!user.isBanned} + title={__.banUser} + onclick={banUser}></i> + <i class="fa fa-times" + title={__.deleteUser} + onclick={deleteUser}></i> + </div> + + </div> + + <form class="user-card-edit" if={editing} onsubmit={saveUser}> + <div class="o-form-element"> + <label class="c-label" for="name">{__.name}</label> + <input type="text" + id="name" + ref="name" + class="c-field" + value={opts.user.name}> + </div> + <div class="o-form-element"> + <label class="c-label" for="name">{__.email}</label> + <input type="email" + id="email" + ref="email" + required + class="c-field {c-field--error: errors.email}" + value={opts.user.email}> + <div class="c-hint c-hint--static c-hint--error" each={error in errors.email}>{error}</div> + </div> + <div class="o-form-element"> + <label class="c-toggle c-toggle--info"> + {__.administrator} + <input type="checkbox" + id="administrator" + ref="administrator" + checked={opts.user.administrator}> + <div class="c-toggle__track"> + <div class="c-toggle__handle"></div> + </div> + </label> + </div> + <div class="actions"> + <div class="actions-left"> + <button type="button" + class="c-button c-button--ghost-info" + onclick={cancelEdition}> + <i class="fa fa-undo" aria-hidden="true"></i> + {__.cancel} + </button> + </div> + <div class="actions-right"> + <button type="submit" + class="c-button c-button--info"> + <i class="fa fa-check" aria-hidden="true"></i> + {__.save} + </button> + </div> + </div> + + </form> + + <script type="es6"> + let session = require("../js/Session"); + this.installBundle(session, "user"); + let userService = require("../js/UserService"); + this.editing = false; + this.errors = {}; + + this.startEdition = () => { + this.editing = true; + }; + + this.cancelEdition = () => { + this.editing = false; + }; + + this.banUser = () => { + if (confirm(this.__.banUserMessage)) { + userService.banUser(this.opts.user.id).then(() => { + this.opts.onUserChange(); + }); + } + }; + + this.deleteUser = () => { + if (confirm(this.__.deleteUserMessage)) { + userService.deleteUser(this.opts.user.id).then(() => { + this.opts.onUserChange(); + }); + } + }; + + this.saveUser = e => { + e.preventDefault(); + e.stopPropagation(); + this.user.name = this.refs.name.value; + this.user.email = this.refs.email.value; + this.user.administrator = this.refs.administrator.checked; + + userService.saveUser(this.user).then(() => { + this.errors = {}; + this.cancelEdition(); + this.opts.onUserChange(); + }, errors => { + this.errors = errors; + this.update(); + }); + }; + </script> + + <style> + + usercard { + display: block; + margin: 5px auto; + border-radius: 4px; + border: 1px solid #13a2ff; + box-shadow: 0 0 1px hsla(0,0%,7%,.6); + padding: 0.5em; + color: #13a2ff; + } + + .user-card-view { + display: flex; + justify-content: space-between; + } + + .user-card-edit .o-form-element .c-label:first-child { + width: 25%; + display: inline-block; + text-align: right; + float: left; + padding-top: 0.5em; + padding-right: 5px; + } + + .user-card-edit .o-form-element .c-field { + width: 75%; + display: inline-block; + } + + .user-card-edit .o-form-element .c-toggle, + .user-card-edit .o-form-element .c-hint { + margin-left: 25%; + } + + </style> +</UserCard> diff --git a/pollen-ui-riot-js/src/main/web/tag/Users.tag.html b/pollen-ui-riot-js/src/main/web/tag/Users.tag.html index 5196209..61bfb85 100644 --- a/pollen-ui-riot-js/src/main/web/tag/Users.tag.html +++ b/pollen-ui-riot-js/src/main/web/tag/Users.tag.html @@ -1,307 +1,95 @@ require("./Pagination.tag.html"); +require("./UserCard.tag.html"); <Users> - <div class="body-container"> - - <div class="container"> - - <div class="legend">{__title}</div> - <table> - <thead> - <tr> - <th onclick="{toggleSort}"> - <div> - {__.name} <i ref="sortName" class="fa fa-sort-amount-asc"></i> - </div> - </th> - <th onclick="{toggleSort}"> - <div> - {__.email} <i ref="sortEmail" class="disabled fa fa-sort"></i> - </div> - </th> - <th> - <div> - {__.administrator} + <div class="container" > + <div show="{loaded}"> + <h1 class="c-heading">{__.title}</h1> + + <div show={users.length > 0} > + <div class="o-form-element sort"> + <label class="c-label" for="sort">{__.sort}</label> + <div class="c-input-group"> + <div class="o-field"> + <select class="c-field" + onchange={selectSort}> + <option value="name">{__.name}</option> + <option value="email">{__.email}</option> + </select> </div> - </th> - <th> - <div>{__.status}</div> - </th> - <th> - <div>{__.actions}</div> - </th> - </tr> - </thead> - <tbody> - <tr each="{user in users}"> - <td> - <a href="#user/{user.id}">{user.name}</a> - </td> - <td>{user.email}</td> - <td> - <input type="checkbox" disabled="disabled" checked="{user.administrator?'checked':''}"> - </td> - <td>{user.status}</td> - <td> - <div if="{user.id!=connectedUser.id}" class="dropdown"> - <a class="header-link"><i class="fa fa-navicon fa-15x"/></a> - <div class="dropdown-content" id="{user.id}"> - <a if="{!user.administrator && !user.isBanned}" onclick="{makeAdmin}">{parent.__.makeAdmin}</a> - <a if="{user.administrator && !user.isBanned}" onclick="{unmakeAdmin}">{parent.__.unmakeAdmin}</a> - <a if="{!user.isBanned}" onclick="{banUser}">{parent.__.banUser}</a> - <a onclick="{deleteUser}">{parent.__.deleteUser}</a> - </div> - </div> - </td> - </tr> - </tbody> - <tfoot> - <tr> - <th colspan="5"> - <div> - <Pagination ref="pagination" sortName='{sortName}' sortValue='false' callback="{callback}"/> - </div> - </th> - </tr> - </tfoot> - </table> + <button class="c-button c-button--brand" + onclick={toggleSort}> + <i class="fa {pagination.desc ? 'fa-sort-amount-desc' : 'fa-sort-amount-asc'}"></i> + </button> + </div> + </div> + + <Pagination pagination={pagination} onchange={refresh}/> + + <UserCard each={user in users} user={user} on-user-change={parent.refresh}/> + + <Pagination pagination={pagination} onchange={refresh}/> + </div> + <div show={users.length === 0} class="c-alert c-alert--info"> + {__.noUser} + </div> </div> - </div> <script type="es6"> - this.session = require("../js/Session"); - let i18nCallback = (locale) => { - this.moment.locale(locale); - this.refreshUsers(); + this.loaded = false; + let session = require("../js/Session"); + this.installBundle(session, "users"); + + this.pagination = { + order: "name", + desc: false, + pageSize: 5, + pageNumber: 0 }; - this.installBundle(this.session, "users", i18nCallback); - - this.moment = require("moment"); - this.moment.locale(this.session.locale); - - this.connectedUser = this.session.getUser(); - - this.sortName = "name"; - this.sortValue = false; // means asc this.users = []; let userService = require("../js/UserService"); - this.reloadPagination = ()=> { - this.pagination.onSortChange(this.sortOwner.getAttribute("sortName"), this.sortValue); - }; - - this.makeAdmin = e => { - let userId = e.target.parentNode.id; - // console.info("user id: " + userId); - userService.makeAdmin(userId).then(()=> { - this.reloadPagination(); - }); - }; - this.unmakeAdmin = e => { - let userId = e.target.parentNode.id; - // console.info("user id: " + userId); - userService.unmakeAdmin(userId).then(()=> { - this.reloadPagination(); - }); - }; - this.banUser = e => { - let userId = e.target.parentNode.id; - // console.info("user id: " + userId); - userService.banUser(userId).then(()=> { - this.reloadPagination(); - }); - }; - this.deleteUser = e => { - let userId = e.target.parentNode.id; - // console.info("user id: " + userId); - if (confirm(this.__deleteUserMessage)) { - userService.deleteUser(userId).then(()=> { - this.reloadPagination(); - }); - } - }; - - this.callback = (pagination) => { - // console.info("Request data with pagination::"); - if (!pagination.order) { - pagination.order = this.sortName; - pagination.desc = this.sortValue; - } - // console.info(pagination); - return userService.users(pagination).then((result) => { + this.refresh = () => { + return userService.users(this.pagination).then((result) => { this.users = result.elements; - // console.info("Users::"); - // console.info(this.users); - this.refreshUsers(); + Object.assign(this.pagination, result.pagination); + this.loaded = true; this.update(); return result; }); }; - this.refreshUsers = () => { - this.users.forEach(u => { - let status = "CREATED"; - if (!u.emailIsValidate) { - status = "VALIDATION"; - } - if (u.isDisabled) { - status = "DISABLE"; - } - if (u.isBanned) { - status = "BANNED"; - } - u.status = this.__[status]; - }); - }; - this.on("mount", () => { - this.pagination = this.tags.pagination; - this.sortOwner = this.refs.sortName; - this.refs.sortName.setAttribute("sortName", "name"); - this.refs.sortEmail.setAttribute("sortName", "email"); - }); - - this.toggleSort = (e) => { - // console.info(this.refs.sortName); - if (this.sortOwner === e.target) { - this.sortOwner.classList.toggle("fa-sort-amount-asc"); - this.sortOwner.classList.toggle("fa-sort-amount-desc"); - this.sortValue = !this.sortValue; - } else { - - this.sortOwner.classList.add("fa-sort"); - this.sortOwner.classList.add("disabled"); - this.sortOwner.classList.remove("fa-sort-amount-desc"); - this.sortOwner.classList.remove("fa-sort-amount-asc"); + this.refresh(); - this.sortOwner = e.target; - - this.sortOwner.classList.remove("disabled"); - this.sortOwner.classList.remove("fa-sort"); - this.sortOwner.classList.remove("fa-sort-amount-desc"); - this.sortOwner.classList.add("fa-sort-amount-asc"); - this.sortValue = true; - } - - this.reloadPagination(); + this.toggleSort = () => { + this.pagination.desc = !this.pagination.desc; + this.refresh(); }; - i18nCallback(); + this.selectSort = (e) => { + this.pagination.order = e.target.value; + this.refresh(); + }; </script> <style> - pagination { - width: 100%; - } - - .fa-15x { - font-size: 1.5em; - } - - .disabled { - color: gray; + .c-heading { + text-align: center; } - .body-container { - max-width: 90%; - } - - .container { - display: flex; - justify-content: space-around; - align-items: center; - flex-direction: column; - background: white; - border: solid 2px #c8ccca; - border-radius: 10px; - padding: 15px 0; - width: 100%; - } - - table { - padding-top: 10px; - } - - th { - text-align: left; - } - - th > div { - justify-content: flex-start; - display: flex; - flex-direction: row; - } - - td:first-child { - width: 300px; - } - - td:nth-child(2) { - width: 300px; - } - - td:nth-child(3) { - width: 120px; - } - - td:nth-child(4) { - width: 170px; - } - - td:nth-child(5) { - width: 170px; - } - - .legend { - width: 100%; - height: 30px; - border-bottom: 1px solid #b2c7d3; - display: flex; - justify-content: center; - align-items: center; - padding-bottom: 10px; - font-size: 20px; - } - - input[type=checkbox] { - width: 20px; - height: 20px; - margin: 2px; - } - - /* The container <div> - needed to position the dropdown content */ - .dropdown { - position: relative; + .o-form-element.sort .c-label:first-child { + width: 70px; display: inline-block; + text-align: right; + float: left; + padding-top: 0.5em; + padding-right: 5px; } - /* Dropdown Content (Hidden by Default) */ - .dropdown-content { - display: none; - position: absolute; - background-color: #f9f9f9; - min-width: 228px; - box-shadow: 0 8px 16px 0 rgba(0, 0, 0, 0.2); - } - - /* Links inside the dropdown */ - .dropdown-content a { - color: black; - padding: 12px 16px; - text-decoration: none; - display: block; - } - - /* Change color of dropdown links on hover */ - .dropdown-content a:hover { - background-color: #f1f1f1; - } - - /* Show the dropdown menu on hover */ - .dropdown:hover .dropdown-content { - display: block; - z-index: 1; + .o-form-element.sort .c-input-group { + width: 200px; } </style> -- To stop receiving notification emails like this one, please contact chorem.org SCM administrator <admin+scm@chorem.org>.
participants (1)
-
chorem.org scm