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 29ccbc0591b65ad75a550aeacf966dced96e0264 Author: Tony CHEMIT <dev@tchemit.fr> Date: Mon Jan 23 16:15:32 2017 +0100 Mise en place des commentaires sur sondage + continue page de vote --- .../chorem/pollen/rest/api/v1/PollenUserApi.java | 3 + pollen-ui-riot-js/src/main/web/i18n.json | 18 ++ .../src/main/web/js/CommentService.js | 55 ++++++ pollen-ui-riot-js/src/main/web/js/FetchService.js | 20 +++ pollen-ui-riot-js/src/main/web/js/Pagination.js | 12 ++ pollen-ui-riot-js/src/main/web/js/PollService.js | 7 + pollen-ui-riot-js/src/main/web/tag/Header.tag | 7 +- pollen-ui-riot-js/src/main/web/tag/Pagination.tag | 130 ++++++++++++++ pollen-ui-riot-js/src/main/web/tag/Pollen.tag | 70 +++++--- pollen-ui-riot-js/src/main/web/tag/SignIn.tag | 5 +- .../src/main/web/tag/poll/CommentPopup.tag | 191 ++++++++++++++++++++ pollen-ui-riot-js/src/main/web/tag/poll/Poll.tag | 112 ++++++++++++ .../src/main/web/tag/poll/PollComments.tag | 194 +++++++++++++++++++++ .../src/main/web/tag/poll/PollSettings.tag | 9 +- .../src/main/web/tag/poll/PollVotes.tag | 5 + .../src/main/web/tag/polls/CreatedPolls.tag | 137 +++++++++++++++ 16 files changed, 945 insertions(+), 30 deletions(-) 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 3b1ac5d..86dbe9e 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 @@ -34,6 +34,8 @@ import org.chorem.pollen.services.service.security.PollenInvalidEmailActivationT import org.debux.webmotion.server.WebMotionController; import org.debux.webmotion.server.call.HttpContext; +import java.util.Objects; + /** * TODO * @@ -51,6 +53,7 @@ public class PollenUserApi extends WebMotionController { public PollenUserBean getConnectedUser(HttpContext context, PollenUserService pollenUserService) { PollenRestApiRequestContext pollenRestApiRequestContext = PollenRestApiRequestContext.getRequestContext(context); PollenUser pollenUser = pollenRestApiRequestContext.getSecurityContext().getPollenUser(); + Objects.requireNonNull(pollenUser,"Could not find connected user"); return pollenUserService.getUser(pollenUser.getTopiaId()); } diff --git a/pollen-ui-riot-js/src/main/web/i18n.json b/pollen-ui-riot-js/src/main/web/i18n.json index 5a7e1aa..68fae6a 100644 --- a/pollen-ui-riot-js/src/main/web/i18n.json +++ b/pollen-ui-riot-js/src/main/web/i18n.json @@ -1,5 +1,14 @@ { "fr": { + "comment_popup_create":"Créer un commentaire", + "comment_popup_edit":"Éditer un commentaire", + "comment_popup_action":"Enregistrer", + "comment_popup_authorPlaceholder":"Saisir votre nom", + "comment_popup_textPlaceholder":"Saisir le commentaire", + "polls_created_title":"Mes sondages", + "polls_created_name":"Nom", + "polls_created_createDate":"Date de création", + "polls_created_status":"Statut", "signup_title": "Créer un compte", "signup_email": "Email", "signup_email_placeholder": "Entrer l'email", @@ -132,6 +141,15 @@ "": "" }, "en": { + "comment_popup_create":"Create a comment", + "comment_popup_edit":"edit a comment", + "comment_popup_action":"Save", + "comment_popup_authorPlaceholder":"Fill your name", + "comment_popup_textPlaceholder":"Fill your comment", + "polls_created_title":"My polls", + "polls_created_name":"Name", + "polls_created_createDate":"Created date", + "polls_created_status":"Status", "signup_title": "Create an account", "signup_email": "Email", "signup_email_placeholder": "Enter your email", diff --git a/pollen-ui-riot-js/src/main/web/js/CommentService.js b/pollen-ui-riot-js/src/main/web/js/CommentService.js new file mode 100644 index 0000000..6604f72 --- /dev/null +++ b/pollen-ui-riot-js/src/main/web/js/CommentService.js @@ -0,0 +1,55 @@ +/*- + * #%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 CommentService extends FetchService { + + getComments(pollId, pagination, permission) { + let args = {paginationParameter: pagination}; + if (permission) { + args.permission = permission; + } + return this.getWithParams("/v1/polls/" + pollId + "/comments", args); + } + + createComment(pollId, form) { + return this.form("/v1/polls/" + pollId + "/comments", {comment: form}); + } + + updateComment(pollId, form, permission) { + let url = "/v1/polls/" + pollId + "/comments/" + form.id; + if (permission) { + url += "?permission=" + permission; + } + return this.form(url, {comment: form}); + } + + deleteComment(pollId, commentId, permission) { + let url = "/v1/polls/" + pollId + "/comments/" + commentId; + if (permission) { + url += "?permission=" + permission; + } + return this.doDelete(url); + } +} + +module.exports = singleton(CommentService); diff --git a/pollen-ui-riot-js/src/main/web/js/FetchService.js b/pollen-ui-riot-js/src/main/web/js/FetchService.js index 8f5dcd9..aff3396 100644 --- a/pollen-ui-riot-js/src/main/web/js/FetchService.js +++ b/pollen-ui-riot-js/src/main/web/js/FetchService.js @@ -69,6 +69,22 @@ class FetchService { return this.fetch(url, "GET"); } + getWithParams(url, params) { + let query = "?"; + let keys = Object.keys(params); + keys.forEach((key) => { + let value = params[key]; + if (typeof value === 'object') { + value = JSON.stringify(value); + } + if (query.length > 1) { + query += "&"; + } + query += key + "=" + value; + }); + return this.fetch(url + query, "GET"); + } + post(url, body) { return this.fetch(url, "POST", null, body); } @@ -77,6 +93,10 @@ class FetchService { return this.fetch(url, "PUT", null, body); } + doDelete(url, body) { + return this.fetch(url, "DELETE", null, body); + } + form(url, data) { let formData = null; if (data) { diff --git a/pollen-ui-riot-js/src/main/web/js/Pagination.js b/pollen-ui-riot-js/src/main/web/js/Pagination.js new file mode 100644 index 0000000..e2ac3ed --- /dev/null +++ b/pollen-ui-riot-js/src/main/web/js/Pagination.js @@ -0,0 +1,12 @@ +class Pagination { + + constructor() { + this.pageNumber = 0; + this.pageSize = 25; + this.order = ""; + this.desc = false; + } + +} + +module.exports = Pagination; \ No newline at end of file diff --git a/pollen-ui-riot-js/src/main/web/js/PollService.js b/pollen-ui-riot-js/src/main/web/js/PollService.js index 7e59e15..4318798 100644 --- a/pollen-ui-riot-js/src/main/web/js/PollService.js +++ b/pollen-ui-riot-js/src/main/web/js/PollService.js @@ -31,6 +31,13 @@ class PollService extends FetchService { return this.form("/v1/polls/create", {poll: form, choices:choices}); } + createdPolls(pagination) { + return this.getWithParams("/v1/polls/created", {paginationParameter: pagination}); + } + + getPoll(pollId) { + return this.get("/v1/polls/"+pollId); + } } module.exports = singleton(PollService); diff --git a/pollen-ui-riot-js/src/main/web/tag/Header.tag b/pollen-ui-riot-js/src/main/web/tag/Header.tag index 583b0d3..75c6841 100644 --- a/pollen-ui-riot-js/src/main/web/tag/Header.tag +++ b/pollen-ui-riot-js/src/main/web/tag/Header.tag @@ -25,14 +25,14 @@ require("./HeaderI18n.tag"); </div> <div class="header-separator"></div> <div class="header-space"></div> - <a class="button header-button header-signin" if="{!user}" href="#signin">{__.signin}</a> + <a class="button header-button header-signin" if="{!user}" onclick="{signIn}">{__.signin}</a> <a class="button header-button header-signup" if="{!user}" href="#signup">{__.signup}</a> <div if="{user}" class="dropdown"> <a class="header-link">{user.email}</a> <div class="dropdown-content"> <a href="#user/profile">{__.myProfile}</a> - <a href="#user/polls">{__.myPolls}</a> + <a href="#polls/created">{__.myPolls}</a> <a href="#user/favoriteLists">{__.myFavoriteLists}</a> <span role="separator" class="divider"></span> <a onclick="{signOut}">{__.signout}</a> @@ -47,6 +47,9 @@ require("./HeaderI18n.tag"); this.installBundle(session, "header"); + this.signIn= ()=> { + route("signin?url="+window.location.hash.substring(1)); + }; this.signOut = () => { let callback = () => { this.user = null; diff --git a/pollen-ui-riot-js/src/main/web/tag/Pagination.tag b/pollen-ui-riot-js/src/main/web/tag/Pagination.tag new file mode 100644 index 0000000..6dfe1ce --- /dev/null +++ b/pollen-ui-riot-js/src/main/web/tag/Pagination.tag @@ -0,0 +1,130 @@ +<Pagination> + + <div class="pagination-controls"> + <div class="pagination-config"> + Résultats par page: + <select ref="pageSize" onchange="{onChangePageSize}"> + <option each="{a in sizes}" value="{a}">{a}</option> + + </select> + </div> + + <div class="pagination-pager"> + <button class="{pageNumber > 0 ? '' : 'disabled'}" onclick="{onPreviousPage}"> + <i class="fa fa-chevron-left"></i> + </button> + <div class="pagination-right"> + Page {pageNumber + 1} sur {lastPageNumber} + </div> + <button class="{(pageNumber + 1) < lastPageNumber ? '' : 'disabled'}" onclick="{onNextPage}"> + <i class="fa fa-chevron-right"></i> + </button> + </div> + </div> + + <script> + + this.on('mount', () => { + this.refs.pageSize.value = this.pageSize; + this.refresh(); + }); + + this.sizes = [1, 5, 10, 15, 25, 50, 100, 250, 500]; + this.pageNumber = 0; + this.lastPageNumber = 0; + this.pageSize = 5; + this.callback = opts.callback; + this.sortName = opts.sortName; + this.sortValue = opts.sortValue; + + this.onContextChange = function (newContext) { + this.paginationContext = newContext; + + console.info("onContextChange"); + console.info(newContext); + let count = this.paginationContext.count; + let size = this.paginationContext.pageSize; + this.lastPageNumber = Math.ceil(count / size); + this.pageNumber = this.paginationContext.currentPage; + this.pageSize = this.paginationContext.pageSize; + this.sortName = this.paginationContext.order; + this.sortValue = !this.paginationContext.desc; + }; + + this.onSortChange = function (sortName, sortValue) { + this.pageNumber = 0; + this.sortName = sortName; + this.sortValue = sortValue; + console.info("on sort change: "+sortName+" --> "+sortValue) + this.refresh(); + }; + this.onChangePageSize = function (e) { + this.pageNumber = 0; + if (e) { + + console.info("Page size change: " + e.target.value) + this.pageSize = e.target.value; + } + this.refresh(); + }; + + this.onPreviousPage = function () { + if (this.pageNumber > 0) { + this.pageNumber--; + this.refresh(); + } + }; + + this.onNextPage = function () { + if (this.pageNumber + 1 < this.lastPageNumber) { + this.pageNumber++; + this.refresh(); + } + }; + + this.refresh = function () { + let pagination = { + pageNumber: this.pageNumber, + pageSize: this.pageSize, + order: this.sortName, + desc: this.sortValue + }; + console.info("Request: "); + console.info(pagination); + this.callback(pagination).then((result) => { + console.info("update pagination"); + console.info(result.pagination); + this.onContextChange(result.pagination); + this.update(); + }); + }; + + </script> + <style> + + .disabled { + color: gray; + cursor: not-allowed; + } + + .pagination-right { + padding-left: 5px; + padding-right: 5px; + } + + .pagination-controls { + padding-top: 10px; + display: flex; + flex-direction: row; + justify-content: space-between; + } + + .pagination-pager { + display: flex; + flex-direction: row; + align-items: center; + justify-self: flex-end; + } + + </style> +</Pagination> \ No newline at end of file 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 de95131..b9fed83 100644 --- a/pollen-ui-riot-js/src/main/web/tag/Pollen.tag +++ b/pollen-ui-riot-js/src/main/web/tag/Pollen.tag @@ -1,23 +1,23 @@ /*- - * #%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% - */ +* #%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% +*/ require("./Header.tag"); require("./Footer.tag"); require("./SignIn.tag"); @@ -25,6 +25,8 @@ require("./SignUp.tag"); require("./SignCheck.tag"); require("./Home.tag"); require("./poll/CreatePoll.tag"); +require("./poll/Poll.tag"); +require("./polls/CreatedPolls.tag"); <Pollen class="body-wrapper"> <Header></Header> <div class="body-content" ref="content"></div> @@ -39,6 +41,10 @@ require("./poll/CreatePoll.tag"); route("/signin", () => { riot.mount(this.refs.content, "signin"); }); + route("/signin..", (url) => { + let q = route.query(); + riot.mount(this.refs.content, "signin", {url: q.url}); + }); route("/signup", () => { riot.mount(this.refs.content, "signup"); }); @@ -51,18 +57,34 @@ require("./poll/CreatePoll.tag"); route("/poll", () => { riot.mount(this.refs.content, "polls"); }); - route("/poll/*", (pollId) => { - riot.mount(this.refs.content, "poll", {pollId}); + + route("/poll/*/vote", (pollId) => { + riot.mount(this.refs.content, "poll", {pollId: pollId, tabName: 'votes'}); + }); + route("/poll/*/vote/*", (pollId, permission) => { + riot.mount(this.refs.content, "poll", {pollId: pollId, tabName: 'votes', permission: permission}); + }); + route("/poll/*/comment", (pollId) => { + riot.mount(this.refs.content, "poll", {pollId: pollId, tabName: 'comments'}); + }); + route("/poll/*/comment/*", (pollId, permission) => { + riot.mount(this.refs.content, "poll", {pollId: pollId, tabName: 'comments', permission: permission}); }); + route("/user/profile", () => { riot.mount(this.refs.content, "userprofile"); }); - route("/user/poll", () => { - riot.mount(this.refs.content, "userpolls"); - }); route("/user/favoriteList", () => { riot.mount(this.refs.content, "userfavoritelists"); }); + + route("/polls/created", () => { + if (!session.isConnected()) { + route("/signin?url=/polls/created"); + } else { + riot.mount(this.refs.content, "createdpolls"); + } + }); route("/poll/new/*/*", (type, step) => { riot.mount(this.refs.content, "createpoll", {type: type, step: step}); }); diff --git a/pollen-ui-riot-js/src/main/web/tag/SignIn.tag b/pollen-ui-riot-js/src/main/web/tag/SignIn.tag index 4b64681..8501483 100644 --- a/pollen-ui-riot-js/src/main/web/tag/SignIn.tag +++ b/pollen-ui-riot-js/src/main/web/tag/SignIn.tag @@ -62,7 +62,10 @@ require("./popup/NewPassword.tag"); authService.signIn(this.refs.login.value, this.refs.password.value) .then(() => { - route(this.opts.link || "/"); + let back = opts.url || "/"; + console.info("After login url:" +back); + route(back); + this.update(); }) .catch((code) => { this.message = this.__.error_signin; diff --git a/pollen-ui-riot-js/src/main/web/tag/poll/CommentPopup.tag b/pollen-ui-riot-js/src/main/web/tag/poll/CommentPopup.tag new file mode 100644 index 0000000..e4801cf --- /dev/null +++ b/pollen-ui-riot-js/src/main/web/tag/poll/CommentPopup.tag @@ -0,0 +1,191 @@ +/*- +* #%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% +*/ +<CommentPopup class="close"> + + <div class="popup-background"></div> + + <div class="popup-content"> + <div class="popup-close" onclick="{close}"> + <i class="fa fa-times"></i> + </div> + <div class="popup-title">{title}</div> + <form class="popup-message" onsubmit="{action}"> + <div class="popup-message-header"> + <div if="{error}" class="error">{error}</div> + </div> + <input ref="author" type="text" required placeholder="{__.authorPlaceholder}"> + <textarea ref="text" required placeholder="{__.textPlaceholder}"/> + <input type="submit" class="button" value="{__.action}"> + </form> + + </div> + + <script> + let session = require("../../js/Session"); + this.installBundle(session, "comment_popup"); + + this.error = ""; + + this.oldParent = this.parent.root; + + this.openForEdit = (pollId, comment, callback) => { + this.title = this.__.edit; + this.open(pollId, comment, callback); + }; + + this.openForCreate = (pollId, comment, callback) => { + this.title = this.__.create; + this.open(pollId, comment, callback); + }; + + this.open = (pollId, comment, callback) => { + this.comment = Object.assign({}, comment); + this.refs.author.value = comment.authorName; + this.refs.text.value = comment.text; + this.pollId = pollId; + this.callback = callback; + this.error = ""; + document.body.appendChild(this.root); + this.root.classList.toggle("close"); + this.root.classList.toggle("open"); + } + + this.close = () => { + this.oldParent.appendChild(this.root); + this.root.classList.toggle("close"); + this.root.classList.toggle("open"); + }; + + this.action = (e) => { + e.preventDefault(); + e.stopPropagation(); + this.error = ""; + this.comment.authorName = this.refs.author.value; + this.comment.text = this.refs.text.value; + this.callback(this.comment).then(result => { + this.close(); + }).catch((e) => { + this.error = e; + this.update(); + }); + }; + </script> + + <style> + commentpopup { + justify-content: center; + align-items: center; + flex-direction: column; + position: absolute; + top: 0; + width: 100%; + height: 100%; + } + + .popup-background { + width: 100%; + height: 100%; + background-color: white; + opacity: .8; + position: absolute; + top: 0; + } + + commentpopup.close { + display: none; + } + + commentpopup.open { + display: flex; + } + + .popup-title { + height: 70px; + border-bottom: 1px solid #b2c7d3; + background-color: white; + display: flex; + justify-content: center; + align-items: center; + margin-bottom: 20px; + font-size: 20px; + } + + .popup-content { + position: relative; + z-index: 1; + border-radius: 10px; + background-color: #f2f2f2; + box-shadow: 0 0 12px 12px rgba(0, 0, 0, 0.1); + } + + .popup-content .button { + padding: 0; + border: none; + border-radius: 0; + width: 100%; + margin: 20px 0 0; + } + + .popup-close { + cursor: pointer; + position: absolute; + top: 20px; + right: 20px; + } + + .popup-message { + display: flex; + flex-direction: column; + width: 420px; + text-align: left; + } + + .popup-message > div { + margin-right: 22px; + } + + .popup-message-header { + display: flex; + flex-direction: row; + justify-content: flex-end; + height: 30px; + } + + .popup-message > input { + width: 390px; + margin-top: 10px; + margin-bottom: 5px; + } + + .popup-message > textarea { + width: 390px; + margin-top: 10px; + margin-bottom: 5px; + } + + .error { + margin: 3px; + color: red; + } + + </style> + +</CommentPopup> diff --git a/pollen-ui-riot-js/src/main/web/tag/poll/Poll.tag b/pollen-ui-riot-js/src/main/web/tag/poll/Poll.tag new file mode 100644 index 0000000..9ef8b61 --- /dev/null +++ b/pollen-ui-riot-js/src/main/web/tag/poll/Poll.tag @@ -0,0 +1,112 @@ +require('./PollVotes.tag'); +require('./PollComments.tag'); +<Poll> + + <div class="container"> + + <div class="legend"> + {poll.title} + </div> + + <div class="tab-header"> + <div class="{selectedTab=='votes'?'tab-selected':'tab-not-selected'}"> + <a href="#poll/{pollId}/vote"> + <i class="fa fa-thumbs-o-up fa-flip-horizontal"></i>Votes + </a> + </div> + <div class="{selectedTab=='comments'?'tab-selected':'tab-not-selected'}"> + <a href="#poll/{pollId}/comment"> + <i class="fa fa-comments-o"></i>Comments + </a> + </div> + + </div> + <div ref="content" class="tab-content"/> + </div> + + <script> + this.poll = {title: ""}; + this.pollId = opts.pollId; + this.selectedTab = opts.tabName; + this.permission = opts.permission; + let session = require("../../js/Session"); + this.installBundle(session, "poll"); + + + this.on('mount', () => { + let pollService = require('../../js/PollService'); + pollService.getPoll(this.pollId).then(result => { + this.poll = result; + console.info(this.poll); + this.update(); + + if (this.selectedTab == 'votes') { + riot.mount(this.refs.content, "pollvotes", { + pollId: this.pollId, + session: session, + permission: this.permission + }); + } + if (this.selectedTab == 'comments') { + riot.mount(this.refs.content, "pollcomments", { + pollId: this.pollId, + session: session, + permission: this.permission + }); + } + }); + + }); + + + </script> + <style> + + .container { + display: flex; + justify-content: space-around; + align-items: flex-start; + flex-direction: column; + background: white; + border: solid 2px #c8ccca; + border-radius: 10px; + padding: 15px 15px; + width: 90%; + margin-left: 20px; + } + + .tab-content { + margin-top: 20px; + min-height: 300px; + } + + .legend { + width: 100%; + height: 30px; + border-bottom: 1px solid #b2c7d3; + display: flex; + justify-content: center; + align-items: center; + padding-bottom: 10px; + font-size: 20px; + } + + .tab-header { + display: flex; + flex-direction: row; + padding-top: 20px; + } + + .tab-header > div { + padding-right: 20px; + } + + .tab-selected { + color: #13a2ff; + } + + .tab-not-selected > a { + color: black; + } + </style> +</Poll> \ No newline at end of file diff --git a/pollen-ui-riot-js/src/main/web/tag/poll/PollComments.tag b/pollen-ui-riot-js/src/main/web/tag/poll/PollComments.tag new file mode 100644 index 0000000..b863063 --- /dev/null +++ b/pollen-ui-riot-js/src/main/web/tag/poll/PollComments.tag @@ -0,0 +1,194 @@ +require('../Pagination.tag'); +require('./CommentPopup.tag'); +<PollComments> + <div class="comment-container"> + <div class="legend"> + Comments <a if="{comments.length > -1}" onclick="{toggleSort}"><i ref="sortOwner" + class="fa fa-sort-amount-desc"></i></a> + </div> + <div class="body"> + + <div if="{comments.length == 0}">Pas de commentaire</div> + <table show="{comments.length > 0}"> + <tbody> + <tr each="{comment in comments}"> + <td> + <div class="comment-header"> + <div> + <i class="fa fa-user"/> + {comment.authorName} + </div> + <div> + <i class="fa fa-calendar-o"/> + {comment.postDate} + </div> + <div if="{comment.permission}" id="{comment.id}"> + <a onclick="{parent.openEditComment}"><i class="fa fa-pencil-square-o"/></a> + <a onclick="{parent.deleteComment}"><i class="fa fa-trash danger"/></a> + </div> + </div> + + </td> + <td> + <div class="comment-content"> + {comment.text} + </div> + </td> + </tr> + </tbody> + <tfoot> + <tr> + <th colspan="3"> + <div> + <Pagination ref=pagination" sortName='"postDate"' sortValue='true' callback="{callback}"/> + </div> + </th> + </tr> + </tfoot> + </table> + + <div class="actions"> + <a class="button mainColorBackground" onclick="{openAddComment}">Ajouter un commentaire</a> + </div> + </div> + </div> + + <CommentPopup ref="commentPopup"/> + + <script> + + let session = require("../../js/Session"); + this.installBundle(session, "poll_comments"); + let commentService = require("../../js/CommentService"); + + this.pollId = opts.pollId; + this.permission = opts.permission; + console.info("permission:: " + this.permission); + this.on('mount', () => { + this.pagination = this.tags.pagination; + }); + + this.sortName = 'postDate'; + this.sortValue = true; // means desc + + this.comments = []; + this.toggleSort = (e) => { + this.refs.sortOwner.classList.toggle('fa-sort-amount-desc'); + this.refs.sortOwner.classList.toggle('fa-sort-amount-asc'); + this.sortValue = !this.sortValue; + this.pagination.onSortChange('postDate', this.sortValue); + }; + + this.openAddComment = (e) => { + let comment = { + text: '', + authorName: '' + }; + if (session.isConnected()) { + comment.authorName = session.user.name; + } + this.refs.commentPopup.openForCreate(this.pollId, comment, this.addComment); + }; + + this.addComment = (comment) => { + return commentService.createComment(this.pollId, comment) + .then((result) => { + console.info("created comment"); + console.info(result); + this.pagination.refresh(); + }); + }; + + this.openEditComment = (e) => { + let commentId = e.target.parentNode.parentNode.id; + this.comments.forEach(comment => { + if (comment.id == commentId) { + console.info('edit comment ' + commentId); + this.refs.commentPopup.openForEdit(this.pollId, comment, this.editComment); + } + }); + + }; + + this.editComment = (comment) => { + return commentService.updateComment(this.pollId, comment, this.permission || comment.permission || '') + .then((result) => { + console.info("updated comment"); + console.info(result); + this.pagination.refresh(); + }); + }; + + this.deleteComment = (e) => { + let commentId = e.target.parentNode.parentNode.id; + this.comments.forEach(comment => { + if (comment.id == commentId) { + let response = confirm('Delete comment ?'); + if (response) { + return commentService.deleteComment(this.pollId, commentId, this.permission || comment.permission || '') + .then((result) => { + console.info("delete comment"); + console.info(result); + this.pagination.onChangePageSize(); + }); + } + } + }); + }; + + this.callback = (pagination) => { + if (!this.pollId) { + return Promise.resolve({elements: []}); + } + console.info("Request data with pagination::"); + if (!pagination.sortName) { + pagination.order = this.sortName; + pagination.desc = this.sortValue; + } + console.info(pagination); + return commentService.getComments(this.pollId, pagination, this.permission).then((result) => { + this.comments = result.elements; + console.info(this.comments); + this.update(); + return result; + }); + }; + + </script> + <style> + .danger { + color: red; + } + + .comment-container { + width: 800px; + } + + .comment-header { + width: 200px; + } + + .legend { + width: 800px; + } + + .actions { + margin-top: 10px; + } + + tr > td:first-child { + border-right: 1px solid #ddd; + } + + tr td { + border-bottom: 1px solid #ddd; + vertical-align: top; + padding: 5px 5px 15px; + } + + table { + width: 800px; + } + + </style> +</PollComments> \ No newline at end of file diff --git a/pollen-ui-riot-js/src/main/web/tag/poll/PollSettings.tag b/pollen-ui-riot-js/src/main/web/tag/poll/PollSettings.tag index 0964d5e..32772fa 100644 --- a/pollen-ui-riot-js/src/main/web/tag/poll/PollSettings.tag +++ b/pollen-ui-riot-js/src/main/web/tag/poll/PollSettings.tag @@ -56,7 +56,7 @@ <a onclick="{scrollTo}" href="#Choice">{__.nav_choices}</a> <ul class="nav nav-stacked"> <li> - <a onclick="{scrollTo}" href="#ChoiceaddChoices">{__.nav_addChoices}</a> + <a onclick="{scrollTo}" href="#Choice_addChoices">{__.nav_addChoices}</a> </li> <li> <a onclick="{scrollTo}" href="#Choice_limitChoices">{__.nav_limitChoices}</a> @@ -269,8 +269,11 @@ let model = this.form.model; let form = this.refs.form; - let FormHelper = require('../../js/FormHelper'); - FormHelper.fillForm(form, model); + if (form) { + let FormHelper = require('../../js/FormHelper'); + FormHelper.fillForm(form, model); + } + }); this.previousStep = (e) => { diff --git a/pollen-ui-riot-js/src/main/web/tag/poll/PollVotes.tag b/pollen-ui-riot-js/src/main/web/tag/poll/PollVotes.tag new file mode 100644 index 0000000..69efb7c --- /dev/null +++ b/pollen-ui-riot-js/src/main/web/tag/poll/PollVotes.tag @@ -0,0 +1,5 @@ +<PollVotes> + <div> + Votes + </div> +</PollVotes> \ No newline at end of file diff --git a/pollen-ui-riot-js/src/main/web/tag/polls/CreatedPolls.tag b/pollen-ui-riot-js/src/main/web/tag/polls/CreatedPolls.tag new file mode 100644 index 0000000..ce76ca7 --- /dev/null +++ b/pollen-ui-riot-js/src/main/web/tag/polls/CreatedPolls.tag @@ -0,0 +1,137 @@ +require('../Pagination.tag'); +<CreatedPolls> + <div class="body-container"> + + <div class="container"> + + <div class="legend">{__.title}</div> + <table> + <thead> + <tr> + <th class="wide" onclick="{toggleSort}">{__.name} <i ref="sortName" + class="fa fa-sort-amount-asc"></i></th> + <th onclick="{toggleSort}">{__.createDate} <i ref="sortCreateDate" + class="disabled fa fa-sort"></i></th> + <th onclick="{toggleSort}">{__.status}</th> + </tr> + </thead> + <tbody> + <tr each="{poll in polls}"> + <td> + <a href="#poll/{poll.id}/vote">{poll.title}</a> + </td> + <td>{poll.beginDate}</td> + <td>{poll.status}</td> + </tr> + </tbody> + <tfoot> + <tr> + <th colspan="3"> + <div> + <Pagination ref=pagination" sortName='{sortName}' sortValue='false' callback="{callback}"/> + </div> + </th> + </tr> + </tfoot> + </table> + </div> + + </div> + + <script> + this.sortName = 'title'; + this.sortValue = false; // means asc + let pollService = require('../../js/PollService'); + this.callback = (pagination) => { + console.info("Request data with pagination::"); + if (!pagination.sortName) { + pagination.order = this.sortName; + pagination.desc = this.sortValue; + } + console.info(pagination); + return pollService.createdPolls(pagination).then((result) => { + this.polls = result.elements; + console.info(this.polls); + this.update(); + return result; + }); + }; + this.polls = null; + + let session = require("../../js/Session"); + this.installBundle(session, "polls_created"); + this.on('mount', () => { + this.pagination = this.tags.pagination; + this.sortOwner = this.refs.sortName; + this.refs.sortName.setAttribute('sortName', 'title'); + this.refs.sortCreateDate.setAttribute('sortName', 'topiaCreatedDate'); + }); + + 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); + }; + + </script> + <style> + + .disabled { + color: gray; + } + + .wide { + width: 400px; + } + + .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: 90%; + } + + table { + padding-top: 10px; + } + + thead > tr > th { + text-align: left; + } + + .legend { + width: 100%; + height: 30px; + border-bottom: 1px solid #b2c7d3; + display: flex; + justify-content: center; + align-items: center; + padding-bottom: 10px; + font-size: 20px; + } + </style> +</CreatedPolls> \ No newline at end of file -- To stop receiving notification emails like this one, please contact chorem.org SCM administrator <admin+scm@chorem.org>.