branch feature/pollen-riot-js updated (702d0f2 -> 371c5fc)
This is an automated email from the git hooks/post-receive script. New change to branch feature/pollen-riot-js in repository pollen. See https://gitlab.nuiton.org/chorem/pollen.git from 702d0f2 quelques retouches de styles new 371c5fc Ajout de la gestion 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 371c5fc99a4e4f0f563a5c28052c98dcee118fcf Author: Tony CHEMIT <dev@tchemit.fr> Date: Thu Feb 2 08:05:28 2017 +0100 Ajout de la gestion des utilisateurs Summary of changes: .../chorem/pollen/rest/api/v1/PollenUserApi.java | 10 + pollen-rest-api/src/main/resources/mapping | 2 + .../pollen/services/service/PollenUserService.java | 24 ++ pollen-ui-riot-js/src/main/web/i18n.json | 28 ++ .../main/web/js/{VoteService.js => UserService.js} | 43 +-- pollen-ui-riot-js/src/main/web/tag/Pollen.tag | 10 + pollen-ui-riot-js/src/main/web/tag/Users.tag | 304 +++++++++++++++++++++ 7 files changed, 402 insertions(+), 19 deletions(-) copy pollen-ui-riot-js/src/main/web/js/{VoteService.js => UserService.js} (57%) create mode 100644 pollen-ui-riot-js/src/main/web/tag/Users.tag -- 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 feature/pollen-riot-js in repository pollen. See https://gitlab.nuiton.org/chorem/pollen.git commit 371c5fc99a4e4f0f563a5c28052c98dcee118fcf Author: Tony CHEMIT <dev@tchemit.fr> Date: Thu Feb 2 08:05:28 2017 +0100 Ajout de la gestion des utilisateurs --- .../chorem/pollen/rest/api/v1/PollenUserApi.java | 10 + pollen-rest-api/src/main/resources/mapping | 2 + .../pollen/services/service/PollenUserService.java | 24 ++ pollen-ui-riot-js/src/main/web/i18n.json | 28 ++ pollen-ui-riot-js/src/main/web/js/UserService.js | 60 ++++ pollen-ui-riot-js/src/main/web/tag/Pollen.tag | 10 + pollen-ui-riot-js/src/main/web/tag/Users.tag | 304 +++++++++++++++++++++ 7 files changed, 438 insertions(+) diff --git a/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/PollenUserApi.java b/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/PollenUserApi.java index 86dbe9e..8931c4a 100644 --- a/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/PollenUserApi.java +++ b/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/PollenUserApi.java @@ -95,6 +95,16 @@ public class PollenUserApi extends WebMotionController { pollenUserService.banUser(userId.getEntityId(), anonymize); } + public void makeAdmin(PollenUserService pollenUserService, PollenEntityId<PollenUser> userId) { + + pollenUserService.makeAdmin(userId.getEntityId()); + } + + public void unmakeAdmin(PollenUserService pollenUserService, PollenEntityId<PollenUser> userId) { + + pollenUserService.unmakeAdmin(userId.getEntityId()); + } + public void validateUserEmail(PollenUserService pollenUserService, PollenEntityId<PollenUser> userId, String token) throws PollenInvalidEmailActivationTokenException { diff --git a/pollen-rest-api/src/main/resources/mapping b/pollen-rest-api/src/main/resources/mapping index d64c8e2..e838a4b 100644 --- a/pollen-rest-api/src/main/resources/mapping +++ b/pollen-rest-api/src/main/resources/mapping @@ -141,6 +141,8 @@ PUT,POST /v1/users/{userId}/password PollenUserApi.changePassword POST /v1/users/{userId}/admin PollenUserApi.adminUser DELETE /v1/users/{userId} PollenUserApi.deleteUser DELETE /v1/users/{userId}/ban PollenUserApi.banUser +POST /v1/users/{userId}/makeAdmin PollenUserApi.makeAdmin +POST /v1/users/{userId}/unmakeAdmin PollenUserApi.unmakeAdmin PUT /v1/users/{userId}?token={} PollenUserApi.validateUserEmail # VoteCountingApi 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 422302f..9f8c7f0 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 @@ -175,6 +175,30 @@ public class PollenUserService extends PollenServiceSupport implements PollenSer getNotificationService().onUserEdited(user); } + public void makeAdmin(String userId) { + + checkNotNull(userId); + checkIsAdmin(); + + PollenUser user = getUser0(userId); + user.setAdministrator(true); + + commit(); + + } + + public void unmakeAdmin(String userId) { + + checkNotNull(userId); + checkIsAdmin(); + + PollenUser user = getUser0(userId); + user.setAdministrator(false); + + commit(); + + } + public void changePassword(String userId, String oldPassword, String newPassword) throws InvalidFormException { diff --git a/pollen-ui-riot-js/src/main/web/i18n.json b/pollen-ui-riot-js/src/main/web/i18n.json index 957e890..78b3af8 100644 --- a/pollen-ui-riot-js/src/main/web/i18n.json +++ b/pollen-ui-riot-js/src/main/web/i18n.json @@ -193,6 +193,20 @@ "poll_created_vote": "Pour voter, veuillez utiliser le lien suivant", "poll_created_editUrl": "Gérer le sondage", "poll_created_voteUrl": "Voter", + "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é", "": "" }, "en": { @@ -391,6 +405,20 @@ "poll_created_vote": "To vote on poll, please use following link", "poll_created_editUrl": "Manage poll", "poll_created_voteUrl": "Vote on poll", + "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", "": "" } } \ No newline at end of file diff --git a/pollen-ui-riot-js/src/main/web/js/UserService.js b/pollen-ui-riot-js/src/main/web/js/UserService.js new file mode 100644 index 0000000..4fdf53d --- /dev/null +++ b/pollen-ui-riot-js/src/main/web/js/UserService.js @@ -0,0 +1,60 @@ +/*- + * #%L + * Pollen :: UI (Riot Js) + * %% + * Copyright (C) 2009 - 2017 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * #L% + */ +let singleton = require("./Singleton"); +let FetchService = require("./FetchService"); + +class UserService extends FetchService { + + users(pagination) { + return this.getWithParams("/v1/users", {paginationParameter: pagination}); + } + + user(userId, permission) { + let url = "/v1/users/" + userId; + if (permission) { + url += "?permission=" + permission; + } + return this.get(url); + } + + makeAdmin(userId) { + let url = "/v1/users/" + userId + "/makeAdmin"; + return this.post(url); + } + + unmakeAdmin(userId) { + let url = "/v1/users/" + userId + "/unmakeAdmin"; + return this.post(url); + } + + deleteUser(userId) { + let url = "/v1/users/" + userId + "?anonymize=true"; + return this.doDelete(url); + } + + banUser(userId) { + let url = "/v1/users/" + userId + "/ban?anonymize=true"; + return this.doDelete(url); + } + +} + +module.exports = singleton(UserService); diff --git a/pollen-ui-riot-js/src/main/web/tag/Pollen.tag b/pollen-ui-riot-js/src/main/web/tag/Pollen.tag index 32756e6..1ce83da 100644 --- a/pollen-ui-riot-js/src/main/web/tag/Pollen.tag +++ b/pollen-ui-riot-js/src/main/web/tag/Pollen.tag @@ -27,6 +27,7 @@ require("./Home.tag"); require("./poll/CreatePoll.tag"); require("./poll/Poll.tag"); require("./poll/Polls.tag"); +require("./Users.tag"); <Pollen class="body-wrapper"> <Header></Header> <div class="body-content" ref="content"></div> @@ -81,6 +82,15 @@ require("./poll/Polls.tag"); } }); + route("/user", () => { + if (!session.isConnected()) { + route("/signin?url=/user"); + } else { + + riot.mount(this.refs.content, "users", {session: session}); + } + }); + route("/poll/*/choice", (pollId) => { riot.mount(this.refs.content, "poll", {pollId: pollId, tabName: 'choices'}); }); diff --git a/pollen-ui-riot-js/src/main/web/tag/Users.tag b/pollen-ui-riot-js/src/main/web/tag/Users.tag new file mode 100644 index 0000000..493faf0 --- /dev/null +++ b/pollen-ui-riot-js/src/main/web/tag/Users.tag @@ -0,0 +1,304 @@ +require('./Pagination.tag'); +<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> + </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}" onclick="{makeAdmin}">{parent.__.makeAdmin}</a> + <a if="{user.administrator}" onclick="{unmakeAdmin}">{parent.__.unmakeAdmin}</a> + <a 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> + </div> + + </div> + + <script> + this.session = require("../js/Session"); + let i18nCallback = (locale) => { + this.moment.locale(locale); + this.refreshUsers(); + }; + this.installBundle(this.session, "users", i18nCallback); + + this.moment = require('moment'); + this.moment.locale(this.session.locale); + + this.session.getUser().then(user=> { + this.connectedUser = user; + }); + + this.sortName = 'name'; + this.sortValue = false; // means asc + this.users = []; + + let userService = require('../js/UserService'); + + + this.makeAdmin = e => { + let userId = e.target.parentNode.id; + console.info('user id: ' + userId); + userService.makeAdmin(userId).then(result=> { + this.pagination.onSortChange(this.sortOwner.getAttribute('sortName'), this.sortValue); + }); + }; + this.unmakeAdmin = e => { + let userId = e.target.parentNode.id; + console.info('user id: ' + userId); + userService.unmakeAdmin(userId).then(result=> { + this.pagination.onSortChange(this.sortOwner.getAttribute('sortName'), this.sortValue); + }); + }; + this.banUser = e => { + let userId = e.target.parentNode.id; + console.info('user id: ' + userId); + userService.banUser(userId).then(result=> { + this.pagination.refresh(); + }); + }; + this.deleteUser = e => { + let userId = e.target.parentNode.id; + console.info('user id: ' + userId); + if (confirm(this.__deleteUserMessage)) { + userService.deleteUser(userId).then(result=> { + this.pagination.refresh(); + }); + } + }; + + 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.users = result.elements; + console.info('Users::'); + console.info(this.users); + this.refreshUsers(); + this.update(); + return result; + }); + }; + + this.refreshUsers = () => { + this.users.forEach(u => { + let status = 'CREATED'; + if (!u.emailIsValidate) { + status = 'VALIDATION'; + } + if (u.isDisabled) { + status = 'DISABLE'; + } + 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.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.pagination.onSortChange(this.sortOwner.getAttribute('sortName'), this.sortValue); + }; + + i18nCallback(); + + </script> + <style> + + pagination { + width: 100%; + } + + .fa-15x { + font-size: 1.5em; + } + + .disabled { + color: gray; + } + + .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; + display: inline-block; + } + + /* 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; + } + + </style> +</Users> \ No newline at end of file -- To stop receiving notification emails like this one, please contact chorem.org SCM administrator <admin+scm@chorem.org>.
participants (1)
-
chorem.org scm