branch feature/options-de-vote updated (e2c8fa0 -> 54d4138)
This is an automated email from the git hooks/post-receive script. New change to branch feature/options-de-vote in repository pollen. See https://gitlab.nuiton.org/chorem/pollen.git from e2c8fa0 Merge branch 'feature/component_choice_editor' into 'develop' new 54d4138 modification d'un sondage 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 54d41384a1c7fb8fa839f54127cca6c4a7b3d6d4 Author: Sylvain Bavencoff <bavencoff@codelutin.com> Date: Mon Mar 13 17:35:01 2017 +0100 modification d'un sondage Summary of changes: 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(-) create mode 100644 pollen-ui-riot-js/src/main/web/tag/poll/editPoll.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 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>.
participants (1)
-
chorem.org scm