This is an automated email from the git hooks/post-receive script. New commit to branch feature/options-de-vote in repository pollen. See https://gitlab.nuiton.org/chorem/pollen.git commit 54d41384a1c7fb8fa839f54127cca6c4a7b3d6d4 Author: Sylvain Bavencoff <bavencoff@codelutin.com> Date: Mon Mar 13 17:35:01 2017 +0100 modification d'un sondage --- pollen-ui-riot-js/src/main/web/css/main.css | 2 +- pollen-ui-riot-js/src/main/web/i18n.json | 4 + pollen-ui-riot-js/src/main/web/js/Poll.js | 21 +- pollen-ui-riot-js/src/main/web/js/PollForm.js | 61 ++++- pollen-ui-riot-js/src/main/web/js/PollService.js | 5 + pollen-ui-riot-js/src/main/web/tag/Pollen.tag.html | 5 +- .../src/main/web/tag/poll/Choice.tag.html | 296 +++++++++++---------- .../src/main/web/tag/poll/Choices.tag.html | 33 ++- .../src/main/web/tag/poll/Description.tag.html | 7 +- .../src/main/web/tag/poll/Poll.tag.html | 79 +++++- .../src/main/web/tag/poll/Settings.tag.html | 57 ++-- .../src/main/web/tag/poll/Voters.tag.html | 5 +- .../src/main/web/tag/poll/Votes.tag.html | 36 +-- .../src/main/web/tag/poll/editPoll.tag.html | 127 +++++++++ 14 files changed, 541 insertions(+), 197 deletions(-) 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 11b8a33..204c028 100644 --- a/pollen-ui-riot-js/src/main/web/css/main.css +++ b/pollen-ui-riot-js/src/main/web/css/main.css @@ -87,7 +87,7 @@ a { .container { max-width: 1024px; - margin: 0 auto; + margin: 15px auto 0 auto; } @media (max-width: 640px) { diff --git a/pollen-ui-riot-js/src/main/web/i18n.json b/pollen-ui-riot-js/src/main/web/i18n.json index 9cbb9cb..99f4f4b 100644 --- a/pollen-ui-riot-js/src/main/web/i18n.json +++ b/pollen-ui-riot-js/src/main/web/i18n.json @@ -5,6 +5,7 @@ "poll_closePoll": "Clôturer le sondage", "poll_reopenPoll": "Réouvrir le sondage", "poll_deletePoll": "Supprimer le sondage", + "poll_editPoll": "Modifier le sondage", "poll_votes": "Votes", "poll_settings": "Configuration", "poll_choices": "Choix", @@ -24,6 +25,7 @@ "poll_comments_cancelEditComment": "Annuler", "poll_comments_deleteComment" : "Voulez-vous supprimer ce commentaire ?", "poll_comments_updateComment": "Valider", + "poll_voteStart": "Les votes ont commencé, certaines options ne sont pas modifiables.", "poll_votes_title": "Votes", "poll_votes_deleteVote": "Supprimer le vote ?", "poll_votes_authorPlaceHolder": "Renseigner votre nom", @@ -240,6 +242,7 @@ "poll_closePoll": "Close poll", "poll_reopenPoll": "Reopen poll", "poll_deletePoll": "Delete poll", + "poll_editPoll": "Edit poll", "poll_results": "Results", "poll_results_noResult": "Results are not yet available.", "poll_results_title": "Results", @@ -257,6 +260,7 @@ "poll_comments_cancelEditComment": "Cancel", "poll_comments_deleteComment" : "Delete comment?", "poll_comments_updateComment": "Valider", + "poll_voteStart": "Votes are started, some options can't be updated.", "poll_votes_title": "Votes", "poll_votes_deleteVote": "Delete vote?", "poll_votes_authorPlaceHolder": "Fill your name", diff --git a/pollen-ui-riot-js/src/main/web/js/Poll.js b/pollen-ui-riot-js/src/main/web/js/Poll.js index 3df6e1d..73c5a29 100644 --- a/pollen-ui-riot-js/src/main/web/js/Poll.js +++ b/pollen-ui-riot-js/src/main/web/js/Poll.js @@ -25,6 +25,19 @@ class Poll { }); } + delete() { + if (this.id) { + return pollService.deletePoll(this.id, this.permission).then(() => { + delete this.id; + delete this.permission; + this.choices = []; + this.votes = []; + this.comments = []; + }); + } + return Promise.reject("Init poll after delete poll"); + } + loadChoices() { if (this.id) { return choiceService.getChoices(this.id, this.permission) @@ -103,8 +116,8 @@ class Poll { close() { if (this.id) { return pollService.closePoll(this.id, this.permission).then(() => { - this.poll.isClosed = true; - this.poll.canVote = false; + this.isClosed = true; + this.canVote = false; return Promise.resolve(this); }); } @@ -114,8 +127,8 @@ class Poll { reopen() { if (this.id) { return pollService.reopenPoll(this.id, this.permission).then(() => { - this.poll.isClosed = false; - this.poll.canVote = true; + this.isClosed = false; + this.canVote = true; return Promise.resolve(this); }); } diff --git a/pollen-ui-riot-js/src/main/web/js/PollForm.js b/pollen-ui-riot-js/src/main/web/js/PollForm.js index cc44013..62897c1 100644 --- a/pollen-ui-riot-js/src/main/web/js/PollForm.js +++ b/pollen-ui-riot-js/src/main/web/js/PollForm.js @@ -22,7 +22,7 @@ let singleton = require("./Singleton"); let Choice = require("./Choice"); let route = require("riot-route"); let voteCountingTypeService = require("./VoteCountingTypeService"); - +let choiceService = require("./ChoiceService"); class PollForm { constructor() { @@ -42,14 +42,33 @@ class PollForm { this.showOptions = false; this.model = {}; this.choices = []; + this.choicesToRemove = []; voteCountingTypeService.getVoteCountingTypes().then(result => { this.voteCountingTypes = result; }); } + loadPoll(pollId, permission) { + return Promise.all([ + this.pollService.getPoll(pollId, permission), + choiceService.getChoices(pollId, permission) + ]).then(results => { + Object.assign(this.model, results[0]); + this.choices = results[1]; + this.showOptions = true; + this.hasVotes = this.model.voteCount > 0; + this.creation = false; + this.choicesToRemove = []; + return Promise.resolve(this); + }); + } + init(choiceType, user) { this.choiceType = choiceType; + this.showOptions = false; + this.hasVotes = false; + this.creation = true; console.info("init form"); return this.pollService.empty(this.choiceType).then((poll) => { @@ -130,6 +149,43 @@ class PollForm { }); } + _saveChoices() { + if (!this.hasVotes) { + let choicesPromises = this.choices.map(choice=> { + let promise; + if (choice.choiceType === "RESOURCE" && choice.choiceValue.type) { + promise = this.resourceService.create(choice.choiceValue) + .then((result) => { + choice.choiceValue = result.id; + return Promise.resolve(choice); + }); + } else { + promise = Promise.resolve(choice); + } + promise.then((choice2) => { + if (choice.id) { + return choiceService.updateChoice(this.model.id, choice2, this.model.permission); + } + return choiceService.addChoice(this.model.id, choice2, this.model.permission); + }); + return promise; + }); + this.choicesToRemove.forEach(choice => { + choicesPromises.push(choiceService.deleteChoice(this.model.id, choice.id, this.model.permission)); + }); + return Promise.all(choicesPromises); + } + return Promise.resolve(); + } + + + save() { + return Promise.all([ + this.pollService.save(this.model), + this._saveChoices() + ]); + } + previousStep() { console.info("previousStep:: " + this.step); console.log (this.choices); @@ -177,6 +233,9 @@ class PollForm { } removeChoice(index) { + if (this.choices[index].id) { + this.choicesToRemove.push(this.choices[index]); + } this.choices.splice(index, 1); } 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 d82de44..536a455 100644 --- a/pollen-ui-riot-js/src/main/web/js/PollService.js +++ b/pollen-ui-riot-js/src/main/web/js/PollService.js @@ -51,6 +51,11 @@ class PollService extends FetchService { return this.getWithParams("/v1/polls", {paginationParameter: pagination}); } + deletePoll(pollId, permission) { + let url = "/v1/polls/" + pollId + "?permission=" + permission; + return this.doDelete(url); + } + getPoll(pollId, permission) { let url = "/v1/polls/" + pollId; if (permission) { 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 9075e83..2b7379d 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 @@ -25,6 +25,7 @@ require("./SignUp.tag.html"); require("./SignCheck.tag.html"); require("./Home.tag.html"); require("./poll/CreatePoll.tag.html"); +require("./poll/editPoll.tag.html"); require("./poll/Poll.tag.html"); require("./poll/Polls.tag.html"); require("./Users.tag.html"); @@ -135,7 +136,9 @@ require("./Users.tag.html"); route("/poll/*/settings/*", (pollId, permission) => { riot.mount(this.refs.content, "poll", {pollId: pollId, tabName: "settings", permission: permission}); }); - + route("/poll/*/edit/*", (pollId, permission) => { + riot.mount(this.refs.content, "editpoll", {pollId: pollId, permission: permission}); + }); route("/poll/*", (pollId) => { riot.mount(this.refs.content, "poll", {pollId: pollId}); }); diff --git a/pollen-ui-riot-js/src/main/web/tag/poll/Choice.tag.html b/pollen-ui-riot-js/src/main/web/tag/poll/Choice.tag.html index 121a05a..ff122b5 100644 --- a/pollen-ui-riot-js/src/main/web/tag/poll/Choice.tag.html +++ b/pollen-ui-riot-js/src/main/web/tag/poll/Choice.tag.html @@ -1,147 +1,161 @@ require("../components/date-picker.tag.html"); require("../components/time-picker.tag.html"); <Choice> - <div class="choice-container"> - <button type="button" class="c-button fa fa-pencil" alt="texte" onclick="{setTextType}"/> - <input type="text" ref="choiceText" class="{choice.choiceType === 'TEXT' ? 'selected' : 'hidden'}" value="{this.opts.choice.choiceType === 'TEXT' ? this.opts.choice.choiceValue : null}"/> - - <button type="button" class="c-button fa fa-image" alt="resource" onclick="{setImageType}"/> - <span if="{originalFile}" class="original-file {choice.choiceType === 'RESOURCE' ? 'selected' : 'hidden'}"> - <span>{originalFile.name}</span><i class="fa fa-remove" onclick="{deleteFile}"/> - </span> - <input type="file" ref="choiceResource" class="{choice.choiceType === 'RESOURCE' ? 'selected' : 'hidden'}" if="{!originalFile}"/> - - <button type="button" class="c-button fa fa-calendar" alt="date" onclick="{setDateType}"/> - <date-picker ref="choiceDate" class="{choice.choiceType.startsWith('DATE') ? 'selected' : 'hidden'}" date="{date}"/> - - <button type="button" class="c-button fa fa-clock-o {!choice.choiceType.startsWith('DATE') ? 'hidden' : ''}" alt="heure" onclick="{toggleTime}"/> - <time-picker ref="choiceTime" class="{choice.choiceType === 'DATETIME' ? 'selected' : 'hidden'}" time="{time}"/> - - <button type="button" class="c-button" alt="description" onclick="{toggleDescription}">...</button> - </div> - <div if="{showDescription}"> - <textarea ref="description" placeholder="{__.description_placeholder}" value="{choice.description}"/> - </div> - - <script type="es6"> - let session = require("../../js/Session"); - let moment = require("moment"); - moment.locale(session.locale); - let Choice = require("../../js/Choice"); - - this.installBundle(session, "choice", locale => { - moment.locale(locale); - }); - - this.number = parseInt(this.opts.number, 10); - this.originalFile = this.opts.choice.choiceType === 'RESOURCE' ? this.opts.choice.choiceValue : null; - this.showDescription = false; - - Object.assign(this.choice = {}, this.opts.choice); - if (this.choice.choiceType.startsWith("DATE")) { - this.date = { - date: moment(parseInt(this.opts.choice.choiceValue, 10)) - }; - } else { - this.date = { - date: moment().startOf('day') - }; - } - - if (this.choice.choiceType === "DATETIME") { - this.time = { - time: moment(parseInt(this.opts.choice.choiceValue, 10)) - }; - } else { - this.time = { - time: moment().startOf('day') - }; - } - - this.setTextType = () => { - this.choice.choiceType = "TEXT"; - }; - - this.setImageType = () => { - this.choice.choiceType = "RESOURCE"; - }; - - this.setDateType = () => { - if (!this.choice.choiceType.startsWith("DATE")) { - this.choice.choiceType = "DATE"; - } - }; - - this.toggleTime = () => { - if (this.choice.choiceType === "DATE") { - this.choice.choiceType = "DATETIME"; - } else if (this.choice.choiceType === "DATETIME") { - this.choice.choiceType = "DATE"; - } - }; - - this.deleteFile = () => { - delete this.originalFile; - }; - - this.toggleDescription = () => { - this.showDescription = !this.showDescription; - }; - - this.getValue = () => { - let choiceValue = {}; - if (this.choice.choiceType === "RESOURCE") { - choiceValue = this.originalFile ? this.originalFile : this.refs.choiceResource.files[0]; - - } else if (this.choice.choiceType.startsWith("DATE")) { - let selectedMoment = this.date.date; - if (this.choice.choiceType === "DATETIME") { - selectedMoment.set({hour: this.time.time.hour(), minute: this.time.time.minute()}); - } - choiceValue = selectedMoment.valueOf(); - - } else { - choiceValue = this.refs.choiceText.value; - } - console.log(choiceValue); - console.log(this.refs.description) - return new Choice(this.choice.choiceType, choiceValue, this.refs.description && this.refs.description.value, this.choice.id); - }; - - /*this.onEditChoice = () => { - this.editing = true; - let ref = this.refs.edit_choice; - ref.classList.add("choice-edit"); - ref.classList.remove("choice-view"); - this.trigger("editChoice", this.number); - Object.assign(this.$choice = {}, this.choice); - // console.info(this.$choice); - }; - - this.cancelEditChoice = () => { - if (this.editing) { - let ref = this.refs.edit_choice; - ref.classList.remove("choice-edit"); - ref.classList.add("choice-view"); - Object.assign(this.choice, this.$choice); - // console.info(this.choice); - this.refs.choice.value = this.choice.choiceValue; - this.refs.description.value = this.choice.description; - - } - this.editing = false; - this.trigger("cancelEditChoice", this.number); - }; - - this.deleteChoice = () => { - if (confirm("Delete choice?")) { - this.trigger("deleteChoice", this.number); - } - };*/ - - </script> - - <style> + <div class="choice-container"> + <button type="button" + class="c-button" + alt="texte" + disabled={opts.disabled} + onclick="{setTextType}"> + <i class="fa fa-pencil" aria-hidden="true"></i> + </button> + <input type="text" + ref="choiceText" + class="{choice.choiceType === 'TEXT' ? 'selected' : 'hidden'}" + disabled={opts.disabled} + value="{opts.choice.choiceType === 'TEXT' ? opts.choice.choiceValue : null}"/> + + <button type="button" + class="c-button" + alt="resource" + show={!opts.disabled} + disabled={opts.disabled} + onclick="{setImageType}"> + <i class="fa fa-image" aria-hidden="true"></i> + </button> + <span if="{originalFile}" + class="original-file {choice.choiceType === 'RESOURCE' ? 'selected' : 'hidden'}"> + <span>{originalFile.name}</span> + <i class="fa fa-remove" + if={!opts.disabled} + onclick="{deleteFile}"/> + </span> + <input type="file" + ref="choiceResource" + class="{choice.choiceType === 'RESOURCE' ? 'selected' : 'hidden'}" + disabled={opts.disabled} + if="{!originalFile}"/> + + <button type="button" + class="c-button" + alt="date" + disabled={opts.disabled} + onclick="{setDateType}"> + <i class="fa fa-calendar" aria-hidden="true"></i> + </button> + <date-picker ref="choiceDate" + class="{choice.choiceType.startsWith('DATE') ? 'selected' : 'hidden'}" + date="{date}"/> + + <button type="button" + class="c-button {!choice.choiceType.startsWith('DATE') ? 'hidden' : ''}" + alt="heure" + disabled={opts.disabled} + onclick="{toggleTime}"> + <i class="fa fa-clock-o " aria-hidden="true"></i> + </button> + <time-picker ref="choiceTime" + class="{choice.choiceType === 'DATETIME' ? 'selected' : 'hidden'}" + time="{time}"/> + + <button type="button" + class="c-button" + alt="description" + onclick="{toggleDescription}"> + ... + </button> + </div> + <div if="{showDescription}"> + <textarea ref="description" + placeholder="{__.description_placeholder}" + disabled={opts.disabled} + value="{choice.description}"/> + </div> + + <script type="es6"> + let session = require("../../js/Session"); + let moment = require("moment"); + moment.locale(session.locale); + + this.installBundle(session, "choice", locale => { + moment.locale(locale); + }); + + this.number = parseInt(this.opts.number, 10); + this.originalFile = this.opts.choice.choiceType === "RESOURCE" ? this.opts.choice.choiceValue : null; + this.showDescription = false; + + this.choice = this.opts.choice; + if (this.choice.choiceType.startsWith("DATE")) { + this.date = { + date: moment(parseInt(this.opts.choice.choiceValue, 10)) + }; + } else { + this.date = { + date: moment().startOf("day") + }; + } + + if (this.choice.choiceType === "DATETIME") { + this.time = { + time: moment(parseInt(this.opts.choice.choiceValue, 10)) + }; + } else { + this.time = { + time: moment().startOf("day") + }; + } + + this.setTextType = () => { + this.choice.choiceType = "TEXT"; + }; + + this.setImageType = () => { + this.choice.choiceType = "RESOURCE"; + }; + + this.setDateType = () => { + if (!this.choice.choiceType.startsWith("DATE")) { + this.choice.choiceType = "DATE"; + } + }; + + this.toggleTime = () => { + if (this.choice.choiceType === "DATE") { + this.choice.choiceType = "DATETIME"; + } else if (this.choice.choiceType === "DATETIME") { + this.choice.choiceType = "DATE"; + } + }; + + this.deleteFile = () => { + delete this.originalFile; + }; + + this.toggleDescription = () => { + this.showDescription = !this.showDescription; + }; + + this.submit = () => { + let choiceValue = {}; + if (this.choice.choiceType === "RESOURCE") { + choiceValue = this.originalFile ? this.originalFile : this.refs.choiceResource.files[0]; + } else if (this.choice.choiceType.startsWith("DATE")) { + let selectedMoment = this.date.date; + if (this.choice.choiceType === "DATETIME") { + selectedMoment.set({hour: this.time.time.hour(), minute: this.time.time.minute()}); + } + choiceValue = selectedMoment.valueOf(); + + } else { + choiceValue = this.refs.choiceText.value; + } + this.choice.choiceValue = choiceValue; + }; + + </script> + + <style> .choice-container { display: flex; diff --git a/pollen-ui-riot-js/src/main/web/tag/poll/Choices.tag.html b/pollen-ui-riot-js/src/main/web/tag/poll/Choices.tag.html index c13fd0c..3dea998 100644 --- a/pollen-ui-riot-js/src/main/web/tag/poll/Choices.tag.html +++ b/pollen-ui-riot-js/src/main/web/tag/poll/Choices.tag.html @@ -1,18 +1,20 @@ require("./Choice.tag.html"); <Choices> <div each={choice, index in form.choices} - class="o-form-element" - ref="choice" > + class="o-form-element"> <div class="c-input-group c-input-group--rounded-left"> <div class="o-field o-field--icon-left"> <i class="c-icon">{index + 1}</i> - <Choice ref={"choice" + index} - class="c-field" - name={"choice" + index} - choice="{choice}"/> + <Choice ref="choice" + class="c-field" + name={"choice" + index} + disabled={form.hasVotes} + choice="{choice}"/> </div> <button type="button" class="c-button c-button--ghost-error" + show={!form.hasVotes} + disabled={form.hasVotes} onclick="{removeChoice(index)}"> <i class="fa fa-trash"/> </button> @@ -21,6 +23,8 @@ require("./Choice.tag.html"); <div class="choices-actions"> <button type="button" class="c-button c-button--brand u-small" + show={!form.hasVotes} + disabled={form.hasVotes} onclick="{addOneChoice}"> <i class="fa fa-plus"/> {__.moreChoice} </button> @@ -32,14 +36,21 @@ require("./Choice.tag.html"); this.choiceType = this.form.choiceType || "TEXT"; this.installBundle(this.session, "poll_choices", this.opts.emitter); - this.addOneChoice = () => this.form.addNewChoice(); + this.addOneChoice = () => { + if (!this.form.hasVotes) { + this.form.addNewChoice(); + } + }; - this.removeChoice = index => () => this.form.removeChoice(index); + this.removeChoice = index => () => { + if (!this.form.hasVotes) { + this.form.removeChoice(index); + } + }; this.submit = () => { - this.form.choices.forEach((choice, index) => { - let editedChoice = this.refs["choice" + index].getValue(); - Object.assign(choice, editedChoice); + this.refs.choice.forEach(choiceTag => { + choiceTag.submit(); }); }; </script> diff --git a/pollen-ui-riot-js/src/main/web/tag/poll/Description.tag.html b/pollen-ui-riot-js/src/main/web/tag/poll/Description.tag.html index b6b93e8..740d411 100644 --- a/pollen-ui-riot-js/src/main/web/tag/poll/Description.tag.html +++ b/pollen-ui-riot-js/src/main/web/tag/poll/Description.tag.html @@ -61,10 +61,13 @@ <style> @media (min-width: 640px) { - .o-form-element .c-label { - width: 24%; + .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 { diff --git a/pollen-ui-riot-js/src/main/web/tag/poll/Poll.tag.html b/pollen-ui-riot-js/src/main/web/tag/poll/Poll.tag.html index 51862a7..f6c2fc7 100644 --- a/pollen-ui-riot-js/src/main/web/tag/poll/Poll.tag.html +++ b/pollen-ui-riot-js/src/main/web/tag/poll/Poll.tag.html @@ -23,6 +23,26 @@ require("./Settings.tag.html"); <i class="fa fa-comments-o fa-15x"></i> {__.comments} ({poll.commentCount}) </a> </div> + <div if="{poll.permission}" + class="poll-options dropdown"> + <a class="header-link"><i class="fa fa-bars"/></a> + <div class="dropdown-content"> + <a if="{!poll.isClosed}" onclick="{closePoll}"> + <i class="link fa fa-close"/> + {__.closePoll}</a> + <a if="{poll.isClosed}" onclick="{reopenPoll}"> + <i class="link fa fa-play"/> + {__.reopenPoll}</a> + <a onclick="{deletePoll}"> + <i class="link fa fa-trash"/> + {__.deletePoll} + </a> + <a href="#/poll/{poll.id}/edit/{poll.permission}"> + <i class="link fa fa-pencil-square-o"/> + {__.editPoll} + </a> + </div> + </div> </div> <div class="container"> @@ -50,17 +70,34 @@ require("./Settings.tag.html"); this.session = require("../../js/Session"); this.installBundle(this.session, "poll"); - this.closePoll = () => { + this.closePoll = (e) => { + e.preventDefault(); + e.stopPropagation(); this.poll.close().then(() => { this.update(); }); }; - this.reopenPoll = () => { + + this.reopenPoll = (e) => { + e.preventDefault(); + e.stopPropagation(); this.poll.reopen().then(() => { this.update(); }); }; + this.deletePoll = (e) => { + e.preventDefault(); + e.stopPropagation(); + let response = confirm(this.__.deletePoll); + if (response) { + this.poll.delete().then(() => { + let route = require("riot-route"); + route("/home"); + }); + } + } + </script> <style> @@ -87,5 +124,43 @@ require("./Settings.tag.html"); border-bottom: 2px solid; } + /* 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: 188px; + box-shadow: 0 8px 16px 0 rgba(0, 0, 0, 0.2); + } + + .dropdown-content.right { + right: 10px; + } + + /* 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> </Poll> diff --git a/pollen-ui-riot-js/src/main/web/tag/poll/Settings.tag.html b/pollen-ui-riot-js/src/main/web/tag/poll/Settings.tag.html index 371a943..63081dc 100644 --- a/pollen-ui-riot-js/src/main/web/tag/poll/Settings.tag.html +++ b/pollen-ui-riot-js/src/main/web/tag/poll/Settings.tag.html @@ -19,7 +19,8 @@ * #L% */ <Settings> - <div class="form-section"> + <div class="form-section" + show={form.creation}> <div class="section-title"> <h4>{__.basic_usage}</h4> </div> @@ -48,7 +49,7 @@ </div> </div> </div> - <div show={showOptions}> + <div show={showOptions || !form.creation}> <hr> <div class="form-section"> <div class="section-title"> @@ -63,6 +64,7 @@ id="choiceAddAllowed" ref="addChoices" checked={form.model.choiceAddAllowed} + disabled={form.hasVotes} onclick="{toggleChoiceAddAllowed}"> <div class="c-toggle__track"> <div class="c-toggle__handle"></div> @@ -78,6 +80,7 @@ name="beginChoiceDate" id="beginChoiceDate" class="c-field" + disabled={form.hasVotes} value={form.model.beginChoiceDate} type="datetime-local"> </div> @@ -89,6 +92,7 @@ name="endChoiceDate" id="endChoiceDate" class="c-field" + disabled={form.hasVotes} value={form.model.endChoiceDate} type="datetime-local"> </div> @@ -100,6 +104,7 @@ name="limitChoices" id="limitChoices" ref="limitChoices" + disabled={form.hasVotes} checked={form.model.limitChoices} onclick="{toggleLimitChoices}"> <div class="c-toggle__track"> @@ -113,7 +118,9 @@ </label> <input name="maxChoiceNumber" id="maxChoiceNumber" + ref="maxChoiceNumber" class="c-field" + disabled={form.hasVotes} value={form.model.maxChoiceNumber} type="number"> </div> @@ -132,6 +139,7 @@ <select class="c-field" ref="voteCountingType" value={form.model.voteCountingType} + disabled={form.hasVotes} onchange={voteCountingTypeChanged}> <option each={type in form.voteCountingTypes} value={type.id}> @@ -169,6 +177,8 @@ <input ref="beginDate" name="beginDate" id="beginDate" + disabled={form.hasVotes} + value={form.model.beginDate} class="c-field" type="datetime-local"> </div> @@ -179,6 +189,7 @@ <input ref="endDate" name="endDate" id="endDate" + value={form.model.endDate} class="c-field" type="datetime-local"> </div> @@ -187,7 +198,10 @@ <label class="c-label"> {__.voteVisibility} </label> - <select class="c-field" ref="voteVisibility" value={form.model.voteVisibility}> + <select class="c-field" + ref="voteVisibility" + disabled={form.hasVotes} + value={form.model.voteVisibility}> <option value="NOBODY">{__.voteVisibility_creator}</option> <option value="VOTER">{__.voteVisibility_voter}</option> <option value="EVERYBODY">{__.voteVisibility_everybody}</option> @@ -200,6 +214,7 @@ name="anonymousVote" id="anonymousVote" ref="anonymousVote" + disabled={form.hasVotes} checked={form.model.anonymousVote} onclick="{toggleAnonymousVote}"> <div class="c-toggle__track"> @@ -219,7 +234,10 @@ <label class="c-label"> {__.resultVisibility} </label> - <select class="c-field" ref="resultVisibility" value={form.model.resultVisibility}> + <select class="c-field" + ref="resultVisibility" + disabled={form.hasVotes} + value={form.model.resultVisibility}> <option value="CREATOR">{__.resultVisibility_creator}</option> <option value="VOTER">{__.resultVisibility_voter}</option> <option value="EVERYBODY">{__.resultVisibility_everybody}</option> @@ -251,7 +269,10 @@ <label class="c-label"> {__.commentVisibility} </label> - <select class="c-field" ref="commentVisibility" value={form.model.commentVisibility}> + <select class="c-field" + ref="commentVisibility" + disabled={form.hasVotes} + value={form.model.commentVisibility}> <option value="CREATOR">{__.commentVisibility_creator}</option> <option value="VOTER">{__.commentVisibility_voter}</option> <option value="EVERYBODY">{__.commentVisibility_everybody}</option> @@ -315,24 +336,26 @@ }; this.submit = () => { - if (!this.showOptions) { + if (!this.showOptions && this.form.creation) { this.form.setSettingsDefault(); } else { - this.form.model.addChoices = this.refs.addChoices.checked; - this.form.model.beginChoiceDate = this.refs.addChoices.checked ? this.refs.beginChoiceDate.value : undefined; - this.form.model.endChoiceDate = this.refs.addChoices.checked ? this.refs.endChoiceDate.value : undefined; - this.form.model.maxChoiceNumber = this.refs.limitChoices.checked ? this.refs.maxChoiceNumber.value : undefined; + if (!this.form.hasVotes) { + this.form.model.addChoices = this.refs.addChoices.checked; + this.form.model.beginChoiceDate = this.refs.addChoices.checked ? this.refs.beginChoiceDate.value : undefined; + this.form.model.endChoiceDate = this.refs.addChoices.checked ? this.refs.endChoiceDate.value : undefined; + this.form.model.maxChoiceNumber = this.refs.limitChoices.checked ? this.refs.maxChoiceNumber.value : undefined; - this.form.model.voteCountingType = this.refs.voteCountingType.value; + this.form.model.voteCountingType = this.refs.voteCountingType.value; - this.form.model.beginDate = this.refs.votePeriod.checked ? this.refs.beginDate.value : undefined; - this.form.model.endDate = this.refs.votePeriod.checked ? this.refs.endDate.value : undefined; - this.form.model.voteVisibility = this.refs.voteVisibility.value; - this.form.model.anonymousVote = this.refs.anonymousVote.value; + this.form.model.beginDate = this.refs.votePeriod.checked ? this.refs.beginDate.value : undefined; + this.form.model.voteVisibility = this.refs.voteVisibility.value; + this.form.model.anonymousVote = this.refs.anonymousVote.value; + this.form.model.resultVisibility = this.refs.resultVisibility.value; + this.form.model.commentVisibility = this.refs.commentVisibility.value; + } - this.form.model.resultVisibility = this.refs.resultVisibility.value; + this.form.model.endDate = this.refs.votePeriod.checked ? this.refs.endDate.value : undefined; this.form.model.continuousResults = this.refs.continuousResults.checked; - this.form.model.commentVisibility = this.refs.commentVisibility.value; } }; 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 58c37e6..5c38372 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 @@ -26,6 +26,7 @@ <select class="c-field" name="pollType" ref="pollType" + disabled={form.hasVotes} value={form.model.pollType} onchange={pollTypeChange} > <option value="FREE">{__.freePoll}</option> @@ -75,7 +76,7 @@ <style> @media (min-width: 640px) { .o-form-element .c-label:first-child { - width: 24%; + width: 25%; display: inline-block; text-align: right; float: left; @@ -89,7 +90,7 @@ } .o-form-element .c-toggle { - margin-left: 24%; + margin-left: 25%; } } diff --git a/pollen-ui-riot-js/src/main/web/tag/poll/Votes.tag.html b/pollen-ui-riot-js/src/main/web/tag/poll/Votes.tag.html index 4feb355..9058916 100644 --- a/pollen-ui-riot-js/src/main/web/tag/poll/Votes.tag.html +++ b/pollen-ui-riot-js/src/main/web/tag/poll/Votes.tag.html @@ -7,7 +7,8 @@ <div if="{voting}" class="voters"> <form ref="formAddVote" onsubmit="{addVote}" class="fix"> <div class="current-voter"> - <div class="o-field o-field--icon-left o-field--icon-right"> + <div class="o-field o-field--icon-left o-field--icon-right" + if={poll.canVote} > <i class="fa fa-fw fa-user c-icon"></i> <input class="c-field {c-field--error: !voteId && error['voter.name']}" type="text" @@ -26,7 +27,8 @@ <div each={choice in poll.choices} class="choice {choice-resource: choice.choiceType === 'RESOURCE'}"> <div id="{choice.id}" class="choice-value"> </div> - <div class="current-choice"> + <div class="current-choice" + if={poll.canVote}> <input if={poll.voteCountingTypeValue.renderType==='checkbox'} class="check" type="checkbox" @@ -42,7 +44,8 @@ </div> </div> <div class="current-voter-actions"> - <button class="c-button c-button--brand pull-right" + <button if={poll.canVote} + class="c-button c-button--brand pull-right" type="submit" name="newVote" disabled={voteId}> @@ -160,18 +163,20 @@ }); this.updateChoices = () => { - this.poll.choices.forEach(c => { - if (c.choiceType === "DATE") { - c.choiceValueStr = this.moment(parseInt(c.choiceValue, 10)).format("LL"); - } else if (c.choiceType === "DATETIME") { - c.choiceValueStr = this.moment(parseInt(c.choiceValue, 10)).format("LLL"); - } else if (c.choiceType === "RESOURCE") { - c.choiceValueStr = ""; - } else { - c.choiceValueStr = c.choiceValue; - } - document.getElementById(c.id).innerHTML = this.md.render(c.choiceValueStr); - }); + if (this.voting) { + this.poll.choices.forEach(c => { + if (c.choiceType === "DATE") { + c.choiceValueStr = this.moment(parseInt(c.choiceValue, 10)).format("LL"); + } else if (c.choiceType === "DATETIME") { + c.choiceValueStr = this.moment(parseInt(c.choiceValue, 10)).format("LLL"); + } else if (c.choiceType === "RESOURCE") { + c.choiceValueStr = ""; + } else { + c.choiceValueStr = c.choiceValue; + } + document.getElementById(c.id).innerHTML = this.md.render(c.choiceValueStr); + }); + } }; this.voteId = null; @@ -285,6 +290,7 @@ flex-wrap: nowrap; justify-content: center; align-items: stretch; + margin-top: 20px; } .voters .fix { diff --git a/pollen-ui-riot-js/src/main/web/tag/poll/editPoll.tag.html b/pollen-ui-riot-js/src/main/web/tag/poll/editPoll.tag.html new file mode 100644 index 0000000..a41e1a6 --- /dev/null +++ b/pollen-ui-riot-js/src/main/web/tag/poll/editPoll.tag.html @@ -0,0 +1,127 @@ +/*- +* #%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("./Description.tag.html"); +require("./Choices.tag.html"); +require("./Settings.tag.html"); +require("./Voters.tag.html"); +require("./Created.tag.html"); + +<EditPoll> + <div class="container" show={loaded}> + + <div class="c-alert c-alert--info" + show={form.hasVotes}> + {__.voteStart} + </div> + + <form ref="poll" onsubmit="{savePoll}" class="form"> + <h2>{__.step_general}</h2> + <Description form={form} session={session}/> + <h2>{__.step_choices}</h2> + <Choices form={form} session={session}/> + <h2>{__.step_options}</h2> + <Settings form={form} session={session}/> + <h2>{__.step_voters}</h2> + <Voters form={form} session={session}/> + <div class="actions"> + <a class="c-button c-button--ghost-info pull-left" + href="#/poll/{form.model.id}/vote/{form.model.permission}"> + <i class="fa fa-undo" aria-hidden="true"></i> + {__.cancel} + </a> + <button type="submit" + class="c-button c-button--info pull-right"> + <i class="fa fa-check" aria-hidden="true"></i> + {__.save} + </button> + </div> + </form> + </div> + + <script type="es6"> + this.loaded = false; + this.form = require("../../js/PollForm"); + this.session = require("../../js/Session"); + this.form.choiceType = this.opts.choiceType; + this.installBundle(this.session, "poll"); + + this.form.loadPoll(this.opts.pollId, this.opts.permission).then(() => { + this.loaded = true; + this.update(); + }); + + this.savePoll = (e) => { + e.preventDefault(); + e.stopPropagation(); + this.tags.description.submit(); + this.tags.choices.submit(); + this.tags.settings.submit(); + this.tags.voters.submit(); + this.form.save().then(() => { + let route = require("riot-route"); + route("poll/" + this.form.model.id + "/vote/" + this.form.model.permission); + }); + }; + + </script> + <style> + + + .steps { + border-bottom: 1px solid #b2c7d3; + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + margin: 0 auto; + } + + .step { + margin-left: 12px; + margin-right: 12px; + } + + .step a { + color : black; + } + + .step.selected { + color: #13a2ff; + border-bottom: 2px solid; + } + + @media (max-width: 640px) { + .step { + display: none; + } + + .step.selected { + display: block; + width: 100%; + text-align: center; + color : black; + border-bottom: none; + } + } + + </style> + +</EditPoll> -- To stop receiving notification emails like this one, please contact chorem.org SCM administrator <admin+scm@chorem.org>.