branch develop updated (20711f24 -> 22eebd62)
This is an automated email from the git hooks/post-receive script. New change to branch develop in repository pollen. See https://gitlab.nuiton.org/chorem/pollen.git from 20711f24 Ajouter le créateur automatiquement dans les participant d'un sondage restreint (ref #155) new 22eebd62 decoupage du composant de vote (ref #165) 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 22eebd62cc97bec7dc27eb325b2cb87aa10d3f3d Author: Sylvain Bavencoff <bavencoff@codelutin.com> Date: Tue Oct 24 14:36:00 2017 +0200 decoupage du composant de vote (ref #165) Summary of changes: .../src/main/web/tag/poll/EditVote.tag.html | 425 ++++++++++++ .../src/main/web/tag/poll/Votes.tag.html | 720 +-------------------- .../src/main/web/tag/poll/VotesTable.tag.html | 346 ++++++++++ 3 files changed, 779 insertions(+), 712 deletions(-) create mode 100644 pollen-ui-riot-js/src/main/web/tag/poll/EditVote.tag.html create mode 100644 pollen-ui-riot-js/src/main/web/tag/poll/VotesTable.tag.html -- To stop receiving notification emails like this one, please contact chorem.org SCM administrator <admin+scm@chorem.org>.
This is an automated email from the git hooks/post-receive script. New commit to branch develop in repository pollen. See https://gitlab.nuiton.org/chorem/pollen.git commit 22eebd62cc97bec7dc27eb325b2cb87aa10d3f3d Author: Sylvain Bavencoff <bavencoff@codelutin.com> Date: Tue Oct 24 14:36:00 2017 +0200 decoupage du composant de vote (ref #165) --- .../src/main/web/tag/poll/EditVote.tag.html | 425 ++++++++++++ .../src/main/web/tag/poll/Votes.tag.html | 720 +-------------------- .../src/main/web/tag/poll/VotesTable.tag.html | 346 ++++++++++ 3 files changed, 779 insertions(+), 712 deletions(-) diff --git a/pollen-ui-riot-js/src/main/web/tag/poll/EditVote.tag.html b/pollen-ui-riot-js/src/main/web/tag/poll/EditVote.tag.html new file mode 100644 index 00000000..831a0bee --- /dev/null +++ b/pollen-ui-riot-js/src/main/web/tag/poll/EditVote.tag.html @@ -0,0 +1,425 @@ +<EditVote> + + <div class="form-wrapper"> + <form id="voteForm" class="voter separator" ref="formAddVote"> + <HumanInput onsubmit="{voteInEdition ? updateVote : addVote}"></HumanInput> + <div class="header"> + <div class="current-voter separator-right"> + <div class="o-field o-field--icon-left o-field--icon-right" + if={poll.canVote || voteInEdition} > + <i class="fa fa-fw fa-user c-icon"></i> + <input class="c-field {c-field--error: !voteInEdition && error && error['voter.name']}" + type="text" + ref="voterName" + name="voterName" + required + maxlength="255" + tabindex="1" + placeholder={__.authorPlaceHolder} + value={poll.voterName}> + </div> + <div if={!poll.canVote && !voteInEdition} + class="choices-label"> + {__.choices} + </div> + </div> + <div if={poll.resultIsVisible} class="result-label"> + <strong>{__.results}</strong> + </div> + </div> + <div each={choice, index in poll.choices} class="choice separator-top"> + <div class="choice-vote separator-right"> + <div class="choice-value"> + <ChoiceView choice={choice} center="true"></ChoiceView> + </div> + <div class="current-choice" + if={poll.canVote || voteInEdition}> + <input if={pollTypeCheckbox} + class="check" + type="checkbox" + onchange="{onVoteChanged}" + ref="{choice.id}_voteValue" + tabindex="{10 * (index + 1)}"> + <input if={!pollTypeCheckbox && !pollTypeSelect} + class="text c-field {c-field--error: !voteInEdition && error && (error['vote.voteValue#' + choice.id] || error['vote.totalVoteValue'])}" + type="number" + required={!poll.voteCountingConfig.maxChoiceNumber} + min="{poll.voteCountingTypeValue && poll.voteCountingTypeValue.minimumValue}" + max="{poll.voteCountingTypeValue && poll.voteCountingTypeValue.maximumValue}" + onchange="{onVoteChanged}" + ref="{choice.id}_voteValue" + tabindex="{10 * (index + 1)}"> + <select if={pollTypeSelect} + class="c-field {c-field--error: !voteInEdition && error && error['vote.voteValue#' + choice.id]}" + required + onchange={onVoteChanged} + tabindex="{10 * (index + 1)}"> + <option value=""></option> + <option each={grad, index in poll.voteCountingConfig.grades} + value={index} + ref="{choice.id}_voteValue"> + {grad} + </option> + </select> + </div> + </div> + <div if={poll.resultIsVisible} class="score-choice"> + <span if={!choice.score}>{parent.__.noVote}</span> + <span if={choice.score}> + <i if="{choice.score.scoreOrder === 0}" class="fa fa-trophy fa-15x winner"></i> + <span if={!pollTypeSelect}> + {choice.score.scoreValue} + {parent.__["results_unit_" + poll.voteCountingType + "_" + (choice.score.scoreValue > 1 ? "many" : "one")]} + </span> + <span if={pollTypeSelect}> + {poll.voteCountingConfig.grades[choice.score.scoreValue]} + </span> + </span> + </div> + </div> + <div class="footer separator-top" if="{poll.choices && (poll.canVote || voteInEdition)}"> + <div class="current-voter-actions separator-right"> + <div class="current-voter-buttons"> + <button if={!voteInEdition} + class="c-button c-button--brand pull-right" + type="submit" + name="newVote" + tabindex="{(poll.choices.length + 1) * 10}" + disabled={tooManyChoicesSelected || voting}> + <i class="fa fa-envelope"></i> + {__.toVote} + </button> + <button if="{voteInEdition}" + class="c-button c-button--error" + type="button" + tabindex="{(poll.choices.length + 2) * 10}" + onclick="{cancelEditVote}" + disabled={voting}> + <i class="fa fa-remove"></i> + {__.cancelEdition} + </button> + <button if="{voteInEdition}" + class="c-button c-button--success" + tabindex="{(poll.choices.length + 1) * 10}" + disabled={tooManyChoicesSelected || voting} + type="submit"> + <i class="fa fa-check"></i> + {__.validateEdition} + </button> + </div> + <div class="c-hint--static c-hint--error" if="{tooManyChoicesSelected}"> + {__.tooManyChoicesSelected} {poll.voteCountingConfig.maxChoiceNumber} + </div> + <div class="c-hint--static c-hint--error" if="{error}"> + <div each={fields in error}> + {fields} + </div> + </div> + </div> + </div> + </form> + </div> + <script type="es6"> + this.loaded = false; + let session = require("../../js/Session"); + let Choice = require("../../js/Choice"); + this.moment = require("moment"); + this.installBundle(session, "poll_votes"); + this.tooManyChoicesSelected = false; + + this.voting = false; + + this.poll = require("../../js/Poll.js"); + this.poll.loadForVotes().then(() => { + this.update(); + }); + + this.onPollChange = poll => { + this.poll = poll; + this.pollTypeCheckbox = poll.voteCountingTypeValue && poll.voteCountingTypeValue.renderType === "checkbox"; + this.pollTypeSelect = poll.voteCountingTypeValue && poll.voteCountingTypeValue.renderType === "select"; + this.onVoteChanged(); + this.update(); + }; + + this.listen("poll", this.onPollChange); + this.listen("user", (user, oldUser) => { + if (user !== oldUser) { + if (user && this.refs.voterName && this.refs.voterName.value !== "") { + this.refs.voterName.value = user.name; + } + this.update(); + } + }); + + this.voteInEdition = null; + this.error = null; + + this.cancelEditVote = () => { + this.voteInEdition = null; + this.resetVoteForm(); + }; + + this.editVote = vote => { + this.voteInEdition = vote; + this.error = null; + this.update(); + this.refs.voterName.value = vote.voterName; + vote.choice.forEach(choice => { + let input = this.refs[choice.choiceId + "_voteValue"]; + if (input) { + if (this.poll.voteCountingTypeValue.renderType === "text") { + input.value = choice.voteValue; + } else if (this.poll.voteCountingTypeValue.renderType === "select") { + input.forEach(option => {option.selected = option.value === choice.voteValue + "";}); + } else { + input.checked = choice.voteValue === 1; + } + } + }); + if (this.poll.voteCountingTypeValue.renderType === "select") { + this.refs[this.poll.choices[0].id + "_voteValue"][0].parentNode.focus(); + } else { + this.refs[this.poll.choices[0].id + "_voteValue"].focus(); + } + }; + + this.getChoiceVoteValue = ref => { + let input = this.refs[ref]; + if (!input) { + return 0; + } + if (this.poll.voteCountingTypeValue.renderType === "text") { + return input.value; + } + if (this.poll.voteCountingTypeValue.renderType === "select") { + return input.find(option => option.selected).value; + } + return input.checked ? 1 : 0; + }; + + this.onVoteChanged = () => { + if (this.loaded && this.poll.voteCountingConfig.maxChoiceNumber) { + var selectedChoiceNb = 0; + this.poll.choices.forEach(c => { + var choiceValue = this.getChoiceVoteValue(c.id + "_voteValue"); + if (choiceValue && choiceValue !== "0") { + selectedChoiceNb++; + } + }); + this.tooManyChoicesSelected = selectedChoiceNb > this.poll.voteCountingConfig.maxChoiceNumber; + } else { + this.tooManyChoicesSelected = false; + } + }; + + this.resetVoteForm = () => { + if (this.poll.canVote) { + this.refs.voterName.value = null; + this.poll.choices.forEach(choice => { + let input = this.refs[choice.id + "_voteValue"]; + if (this.poll.voteCountingTypeValue.renderType === "text") { + input.value = ""; + } else if (this.poll.voteCountingTypeValue.renderType === "select") { + input.forEach(option => {option.selected = false;}); + } else { + input.checked = ""; + } + }); + } + this.selectedChoiceNb = 0; + this.error = null; + }; + + this.addVote = (e) => { + e.preventDefault(); + e.stopPropagation(); + + this.voting = true; + this.update(); + + let vote = { + id: null, + voterName: this.refs.voterName.value, + choice: [] + }; + + this.poll.choices.forEach(c => { + vote.choice.push({ + choiceId: c.id, + voteValue: this.getChoiceVoteValue(c.id + "_voteValue") + }); + }); + + this.poll.addVote(vote).then(() => { + this.resetVoteForm(); + if (this.poll.resultIsVisible) { + this.poll.loadResults().then(() => { + this.voting = false; + this.update(); + }, () => { + this.voting = false; + this.update(); + }); + } else { + this.voting = false; + this.update(); + } + }, + (error) => { + this.error = error; + this.voting = false; + this.update(); + }); + }; + + this.updateVote = e => { + e.preventDefault(); + e.stopPropagation(); + + this.voting = true; + this.update(); + + let updateVote = Object.assign({}, this.voteInEdition); // don't modify original vote + updateVote.voterName = this.refs.voterName.value; + + this.poll.choices.forEach(choice => { + let voteChoice = this.poll.getVoteChoice(updateVote, choice); + if (!voteChoice) { + voteChoice = { + choiceId: choice.id + }; + updateVote.choice.push(voteChoice); + } + voteChoice.voteValue = this.getChoiceVoteValue(choice.id + "_voteValue"); + }); + + this.poll.updateVote(updateVote).then(() => { + this.voteInEdition = null; + this.resetVoteForm(); + if (this.poll.resultIsVisible) { + this.poll.loadResults().then(() => { + this.voting = false; + this.update(); + }, () => { + this.voting = false; + this.update(); + }); + } else { + this.voting = false; + this.update(); + } + }, + (error) => { + this.voting = false; + this.error = error; + this.update(); + }); + }; + + </script> + <style> + + .form-wrapper { + display: flex; + flex-direction: row; + justify-content: center; + align-items: stretch; + } + + .voter { + display: flex; + flex-direction: column; + flex-wrap: nowrap; + margin-top: 20px; + justify-content: center; + align-items: stretch; + } + + .voter > div { + flex-grow: 0; + display: flex; + flex-direction: row; + min-height: 40px; + } + + .voter .header > * { + height: 40px; + text-align: center; + padding: 3px; + line-height: 35px; + } + + .voter .header .current-voter { + flex-grow: 1; + min-width: 200px; + } + + .voter .result-label, .voter .score-choice, .voter .results-actions { + width: 120px; + min-width: 120px; + flex-grow: 0; + text-align: center; + padding: 3px; + align-self: center; + } + + .voter .choice { + flex-wrap: nowrap; + align-items: stretch; + justify-content: center; + } + + .voter .choice .choice-vote { + display: flex; + flex-direction: row; + flex-wrap: nowrap; + align-items: center; + justify-content: center; + flex-grow: 1; + } + + .voter .choice .choice-value { + flex-grow: 1; + font-size: 1.2em; + min-width: 0; + padding: 5px; + } + + .voter .choice .current-choice { + display: flex; + justify-content: center; + min-width: 50px; + } + + .voter .current-voter-actions { + display: flex; + flex-direction: column; + flex-grow: 1; + } + + .voter .current-voter-buttons { + display: flex; + flex-direction: row; + padding: 5px; + justify-content: center; + align-items: center; + } + + .check { + width: 25px; + height: 25px; + } + + .text { + width: 60px; + height: 30px; + margin: 0 0 0 5px; + } + + .choice.c-field { + padding: 0 0 0 1px; + } + + </style> +</EditVote> 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 195c0f10..2ad0b406 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 @@ -20,136 +20,17 @@ --> require("./Choice.tag.html"); require("./ChoiceView.tag.html"); -require("./Podium.tag.html"); +require("./EditVote.tag.html"); +require("./VotesTable.tag.html"); require("../components/HumanInput.tag.html"); require("../components/LazyLoad.tag.html"); require("../components/Avatar.tag.html"); <Votes> <div class="container" show="{loaded}"> - <!-- Form to vote --> - <div class="form-wrapper"> - <form id="voteForm" class="voter separator" ref="formAddVote"> - <HumanInput onsubmit="{voteInEdition ? updateVote : addVote}"></HumanInput> - <div class="header"> - <div class="current-voter separator-right"> - <div class="o-field o-field--icon-left o-field--icon-right" - if={poll.canVote || voteInEdition} > - <i class="fa fa-fw fa-user c-icon"></i> - <input class="c-field {c-field--error: !voteInEdition && error && error['voter.name']}" - type="text" - ref="voterName" - name="voterName" - required - maxlength="255" - tabindex="1" - placeholder={__.authorPlaceHolder} - value={poll.voterName}> - </div> - <div if={!poll.canVote && !voteInEdition} - class="choices-label"> - {__.choices} - </div> - </div> - <div if={poll.resultIsVisible} class="result-label"> - <strong>{__.results}</strong> - </div> - </div> - <div each={choice, index in poll.choices} class="choice separator-top"> - <div class="choice-vote separator-right"> - <div class="choice-value"> - <ChoiceView choice={choice} center="true"></ChoiceView> - </div> - <div class="current-choice" - if={poll.canVote || voteInEdition}> - <input if={pollTypeCheckbox} - class="check" - type="checkbox" - onchange="{onVoteChanged}" - ref="{choice.id}_voteValue" - tabindex="{10 * (index + 1)}"> - <input if={!pollTypeCheckbox && !pollTypeSelect} - class="text c-field {c-field--error: !voteInEdition && error && (error['vote.voteValue#' + choice.id] || error['vote.totalVoteValue'])}" - type="number" - required={!poll.voteCountingConfig.maxChoiceNumber} - min="{poll.voteCountingTypeValue && poll.voteCountingTypeValue.minimumValue}" - max="{poll.voteCountingTypeValue && poll.voteCountingTypeValue.maximumValue}" - onchange="{onVoteChanged}" - ref="{choice.id}_voteValue" - tabindex="{10 * (index + 1)}"> - <select if={pollTypeSelect} - class="c-field {c-field--error: !voteInEdition && error && error['vote.voteValue#' + choice.id]}" - required - onchange={onVoteChanged} - tabindex="{10 * (index + 1)}"> - <option value=""></option> - <option each={grad, index in poll.voteCountingConfig.grades} - value={index} - ref="{choice.id}_voteValue"> - {grad} - </option> - </select> - </div> - </div> - <div if={poll.resultIsVisible} class="score-choice"> - <span if={!choice.score}>{parent.__.noVote}</span> - <span if={choice.score}> - <i if="{choice.score.scoreOrder === 0}" class="fa fa-trophy fa-15x winner"></i> - <span if={!pollTypeSelect}> - {choice.score.scoreValue} - {parent.__["results_unit_" + poll.voteCountingType + "_" + (choice.score.scoreValue > 1 ? "many" : "one")]} - </span> - <span if={pollTypeSelect}> - {poll.voteCountingConfig.grades[choice.score.scoreValue]} - </span> - </span> - </div> - </div> - <div class="footer separator-top" if="{loaded && (poll.canVote || voteInEdition)}"> - <div class="current-voter-actions separator-right"> - <div class="current-voter-buttons"> - <button if={!voteInEdition} - class="c-button c-button--brand pull-right" - type="submit" - name="newVote" - tabindex="{(poll.choices.length + 1) * 10}" - disabled={tooManyChoicesSelected || voting}> - <i class="fa fa-envelope"></i> - {__.toVote} - </button> - <button if="{voteInEdition}" - class="c-button c-button--error" - type="button" - tabindex="{(poll.choices.length + 2) * 10}" - onclick="{cancelEditVote}" - disabled={voting}> - <i class="fa fa-remove"></i> - {__.cancelEdition} - </button> - <button if="{voteInEdition}" - class="c-button c-button--success" - tabindex="{(poll.choices.length + 1) * 10}" - disabled={tooManyChoicesSelected || voting} - type="submit"> - <i class="fa fa-check"></i> - {__.validateEdition} - </button> - </div> - <div class="c-hint--static c-hint--error" if="{tooManyChoicesSelected}"> - {__.tooManyChoicesSelected} {poll.voteCountingConfig.maxChoiceNumber} - </div> - <div class="c-hint--static c-hint--error" if="{error}"> - <div each={fields in error}> - {fields} - </div> - </div> - </div> - <div if={poll.resultIsVisible} class="results-actions"> + <EditVote ref="editVote"/> - </div> - </div> - </form> - </div> + <!-- Form to vote --> <p class="warning-label warning" if="{loaded && !poll.canVote}"> <span if="{moment().isBefore(poll.beginDate)}">{__.voteNotOpen}</span> <span if="{moment().isAfter(poll.endDate)}">{__.voteClosed}</span> @@ -178,335 +59,32 @@ require("../components/Avatar.tag.html"); </form> <!-- Show votes --> - <div class="voters" if="{poll.resultIsVisible && poll.voteCount > 0}"> - <div class="row header separator-bottom"> - <div></div> - <div class="choices separator-left" if="{showChoiceHeader}"> - <div each="{choice in poll.choices}" class="choice separator-top separator-right" - onmouseenter="{parent.showTooltip(null, choice)}" onclick="{parent.showTooltip(null, choice)}" onmouseleave="{parent.hideTooltip}"> - <ChoiceView choice={choice} center="true" hideReport="true"></ChoiceView> - </div> - </div> - </div> - <LazyLoad pagination={pagination} onload={lazyLoad} load-size="20" not-load-on-start="true" ref="lazyLoad" class="elements"> - <yield to="element"> - <div class="row separator-bottom separator-right"> - <div class="name separator-left"> - <Avatar class="voter-avatar" avatar={element.voterAvatar} name={element.voterName} rounded="true"/> - <div class="voter-name" onmouseenter="{parent.parent.showTooltip(element)}" onclick="{parent.parent.showTooltip(vote)}" onmouseleave="{parent.parent.hideTooltip}"> - <span if="{!element.anonymous || element.permission}">{element.voterName}</span> - <span if="{element.anonymous && !element.permission}" class="anonymous-voter">{parent.parent.__.anonymousVoter}</span> - </div> - <button type="button" - class="c-button c-button--rounded u-xsmall c-button--brand" - if="{!parent.parent.poll.closed && element.permission}" - disabled="{parent.parent.voteInEdition != null || parent.parent.voting}" - onclick="{parent.parent.onEditVote(element)}"> - <i class="fa fa-pencil-square-o"></i> - </button> - <button type="button" - class="c-button c-button--rounded u-xsmall c-button--error" - if="{!parent.parent.poll.closed && (parent.parent.poll.permission || element.permission)}" - disabled="{parent.parent.voteInEdition != null || parent.parent.voting}" - onclick="{parent.parent.deleteVote(element)}"> - <i class="fa fa-trash"></i> - </button> - </div> - <div class="results separator-left {'ignored': element.ignored}" ref="results{index}"> - <div each="{choice in parent.parent.poll.choices}" - class="result separator-right {'checkbox' : parent.parent.pollTypeCheckbox} {'selected' : parent.parent.pollTypeCheckbox && parent.parent.poll.getVoteValue(element, choice) == 1}" - onmouseenter="{parent.parent.parent.showTooltip(element, choice)}" onclick="{parent.parent.parent.showTooltip(element, choice)}" onmouseleave="{parent.parent.parent.hideTooltip}"> - <span if="{!pollTypeCheckbox}">{parent.parent.parent.poll.getVoteValue(element, choice)}</span> - </div> - </div> - </div> - </yield> - <yield to="loading"> - <div class="row separator-bottom separator-right"> - <div class="name separator-left"> - <div class="voter-name"> - <i class="fa fa-user-circle c-icon"></i> - <i class="fa fa-spinner fa-pulse"></i> - </div> - </div> - <div class="results separator-left" ref="results{index}"> - <div each="{choice in parent.poll.choices}" - class="result separator-right"> - <i class="fa fa-spinner fa-pulse"></i> - </div> - </div> - </div> - </yield> - </LazyLoad> - <div class="vote-tooltip" ref="voteTooltip" show="{voteTooltip.show}"> - <ChoiceView if="{voteTooltip.choice}" - choice="{voteTooltip.choice}" center="true" hideReport="true"></ChoiceView> - <div class="vote-value" if="{!pollTypeCheckbox && voteTooltip.vote && voteTooltip.choice}"> - {voteTooltip.vote.ignored ? __.ignored :poll.getVoteValue(voteTooltip.vote, voteTooltip.choice)}</div> - <div if="{voteTooltip.vote && !voteTooltip.choice}">{voteTooltip.vote.voterName}</div> - </div> - </div> + <VotesTable if="{poll.resultIsVisible && poll.voteCount > 0}" /> </div> <script type="es6"> - const MIN_CHOICE_COLUMN_WIDTH = 100; this.loaded = false; let session = require("../../js/Session"); let Choice = require("../../js/Choice"); this.moment = require("moment"); this.installBundle(session, "poll_votes"); - this.tooManyChoicesSelected = false; - this.showChoiceHeader = true; - this.voteTooltip = { - show: false, - choice: null, - vote: null - }; - this.voting = false; this.addingChoice = false; this.poll = require("../../js/Poll.js"); - this.poll.loadForVotes().then(() => { - this.refresh(); - this.update(); - }); - - this.pagination = { - order: "topiaCreateDate", - desc: true - }; - - this.lazyLoad = pagination => { - return this.poll.loadLazyVotes(pagination).then((result) => { - return result; - }); - }; - - this.refresh = () => { - this.refs.lazyLoad && this.refs.lazyLoad.reload().then(() => { - this.updateShowChoiceContainer(); - this.update(); - }, () => {}); - }; this.choiceToAdd = this.poll.initChoice(); - this.updateShowChoiceContainer = () => { - let results0 = this.refs.lazyLoad && this.refs.lazyLoad.refs.results0; - this.showChoiceHeader = results0 && this.poll.choices && results0.offsetWidth / this.poll.choices.length >= MIN_CHOICE_COLUMN_WIDTH; - }; - this.onPollChange = poll => { this.loaded = poll.choices !== undefined; this.poll = poll; - this.pollTypeCheckbox = poll.voteCountingTypeValue && poll.voteCountingTypeValue.renderType === "checkbox"; - this.pollTypeSelect = poll.voteCountingTypeValue && poll.voteCountingTypeValue.renderType === "select"; - this.choiceToAdd = this.poll.initChoice(this.choiceToAdd); - this.onVoteChanged(); - this.refresh(); this.update(); }; this.listen("poll", this.onPollChange); - this.listen("user", (user, oldUser) => { - if (user !== oldUser) { - this.refresh(); - this.update(); - } - }); - - this.voteInEdition = null; - this.error = null; - - this.cancelEditVote = () => { - this.voteInEdition = null; - this.resetPoll(); - }; - - this.onEditVote = (vote) => () => { - this.voteInEdition = vote; - this.error = null; - this.update(); - this.refs.voterName.value = vote.voterName; - vote.choice.forEach(choice => { - let input = this.refs[choice.choiceId + "_voteValue"]; - if (input) { - if (this.poll.voteCountingTypeValue.renderType === "text") { - input.value = choice.voteValue; - } else if (this.poll.voteCountingTypeValue.renderType === "select") { - input.forEach(option => {option.selected = option.value === choice.voteValue + "";}); - } else { - input.checked = choice.voteValue === 1; - } - } - }); - if (this.poll.voteCountingTypeValue.renderType === "select") { - this.refs[this.poll.choices[0].id + "_voteValue"][0].parentNode.focus(); - } else { - this.refs[this.poll.choices[0].id + "_voteValue"].focus(); - } - }; - - this.getChoiceVoteValue = ref => { - let input = this.refs[ref]; - if (!input) { - return 0; - } - if (this.poll.voteCountingTypeValue.renderType === "text") { - return input.value; - } - if (this.poll.voteCountingTypeValue.renderType === "select") { - return input.find(option => option.selected).value; - } - return input.checked ? 1 : 0; - }; - - this.onVoteChanged = () => { - if (this.loaded && this.poll.voteCountingConfig.maxChoiceNumber) { - var selectedChoiceNb = 0; - this.poll.choices.forEach(c => { - var choiceValue = this.getChoiceVoteValue(c.id + "_voteValue"); - if (choiceValue && choiceValue !== "0") { - selectedChoiceNb++; - } - }); - this.tooManyChoicesSelected = selectedChoiceNb > this.poll.voteCountingConfig.maxChoiceNumber; - } else { - this.tooManyChoicesSelected = false; - } - }; - this.resetPoll = () => { - if (this.poll.canVote) { - this.refs.voterName.value = null; - this.poll.choices.forEach(choice => { - let input = this.refs[choice.id + "_voteValue"]; - if (this.poll.voteCountingTypeValue.renderType === "text") { - input.value = ""; - } else if (this.poll.voteCountingTypeValue.renderType === "select") { - input.forEach(option => {option.selected = false;}); - } else { - input.checked = ""; - } - }); - } - this.selectedChoiceNb = 0; - this.error = null; - }; - - this.addVote = (e) => { - e.preventDefault(); - e.stopPropagation(); - - this.voting = true; - this.update(); - - let vote = { - id: null, - voterName: this.refs.voterName.value, - choice: [] - }; - - this.poll.choices.forEach(c => { - vote.choice.push({ - choiceId: c.id, - voteValue: this.getChoiceVoteValue(c.id + "_voteValue") - }); - }); - - this.poll.addVote(vote).then(() => { - this.resetPoll(); - if (this.poll.resultIsVisible) { - this.poll.loadResults().then(() => { - this.voting = false; - this.updateShowChoiceContainer(); - this.update(); - }, () => { - this.voting = false; - this.update(); - }); - } else { - this.voting = false; - this.update(); - } - }, - (error) => { - this.error = error; - this.voting = false; - this.update(); - }); - }; - - this.updateVote = e => { - e.preventDefault(); - e.stopPropagation(); - - this.voting = true; - this.update(); - - let updateVote = Object.assign({}, this.voteInEdition); // don't modify original vote - updateVote.voterName = this.refs.voterName.value; - - this.poll.choices.forEach(choice => { - let voteChoice = this.poll.getVoteChoice(updateVote, choice); - if (!voteChoice) { - voteChoice = { - choiceId: choice.id - }; - updateVote.choice.push(voteChoice); - } - voteChoice.voteValue = this.getChoiceVoteValue(choice.id + "_voteValue"); - }); - - this.poll.updateVote(updateVote).then(() => { - this.voteInEdition = null; - this.resetPoll(); - if (this.poll.voteIsVisible) { - this.refresh(); - } - if (this.poll.resultIsVisible) { - this.poll.loadResults().then(() => { - this.voting = false; - this.update(); - }, () => { - this.voting = false; - this.update(); - }); - } else { - this.voting = false; - this.update(); - } - }, - (error) => { - this.voting = false; - this.error = error; - this.update(); - }); - }; - - this.deleteVote = (vote) => (e) => { - e.preventDefault(); - e.stopPropagation(); - - this.confirm(this.__.delete).then((confirm) => { - if (confirm) { - this.voting = true; - this.update(); - - this.poll.deleteVote(vote).then(() => { - this.selectedChoiceNb = 0; - this.updateShowChoiceContainer(); - this.voting = false; - this.update(); - }, - (error) => { - this.voting = false; - this.error = error; - this.update(); - }); - } - }); + this.editVote = (vote) => () => { + this.refs.editVote.editVote(vote); }; this.addChoice = (e) => { @@ -529,146 +107,8 @@ require("../components/Avatar.tag.html"); }); }; - document.body.onresize = () => { - this.updateShowChoiceContainer(); - this.update(); - }; - - this.tooltipTimeout = null; - - this.showTooltip = (vote, choice) => (e) => { - e.preventDefault(); - e.stopPropagation(); - - this.tooltipTimeout = setTimeout(() => { - this.voteTooltip = { - choice: choice, - vote: vote, - show: choice || !vote || !vote.anonymous - }; - this.update(); - if (this.voteTooltip.show) { - let voteTooltip = this.refs.voteTooltip; - voteTooltip.style.top = (e.target.offsetTop + e.target.offsetHeight + 10) + "px"; - voteTooltip.style.left = (e.target.offsetLeft + (e.target.offsetWidth - voteTooltip.offsetWidth) / 2) + "px"; - } - }, 500); - }; - - this.hideTooltip = (e) => { - e.preventDefault(); - e.stopPropagation(); - clearTimeout(this.tooltipTimeout); - this.tooltipTimeout = null; - if (this.voteTooltip.show) { - this.voteTooltip = { - choice: null, - vote: null, - show: false - }; - this.update(); - } - }; - </script> - <style> - - .form-wrapper { - display: flex; - flex-direction: row; - justify-content: center; - align-items: stretch; - } - - .voter { - display: flex; - flex-direction: column; - flex-wrap: nowrap; - margin-top: 20px; - justify-content: center; - align-items: stretch; - } - - .voter > div { - flex-grow: 0; - display: flex; - flex-direction: row; - min-height: 40px; - } - - .voter .header > * { - height: 40px; - text-align: center; - padding: 3px; - line-height: 35px; - } - - .voter .header .current-voter { - flex-grow: 1; - min-width: 200px; - } - - .voter .result-label, .voter .score-choice, .voter .results-actions { - width: 120px; - min-width: 120px; - flex-grow: 0; - text-align: center; - padding: 3px; - align-self: center; - } - - .voter .choice { - flex-wrap: nowrap; - align-items: stretch; - justify-content: center; - } - - .voter .choice .choice-vote { - display: flex; - flex-direction: row; - flex-wrap: nowrap; - align-items: center; - justify-content: center; - flex-grow: 1; - } - - .voter .choice .choice-value { - flex-grow: 1; - font-size: 1.2em; - min-width: 0; - padding: 5px; - } - - .voter .choice .current-choice { - display: flex; - justify-content: center; - min-width: 50px; - } - - .voter .current-voter-actions { - display: flex; - flex-direction: column; - flex-grow: 1; - } - - .voter .current-voter-buttons { - display: flex; - flex-direction: row; - padding: 5px; - justify-content: center; - align-items: center; - } - - .check { - width: 25px; - height: 25px; - } - - .text { - width: 60px; - height: 30px; - margin: 0 0 0 5px; - } + <style> .choice.c-field { padding: 0 0 0 1px; @@ -678,150 +118,6 @@ require("../components/Avatar.tag.html"); margin-top: 20px; } - .voters { - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - margin-top: 50px; - } - - .voters .elements, - .voters .loading { - width: 100%; - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - } - - .voters .row { - display: flex; - width: 95%; - align-items: center; - } - - .voters .row > :first-child { - width: 200px; - min-width: 200px; - display: flex; - height: 2em; - padding: 0 5px; - } - - .voters .row:not(:first-child):hover { - border-bottom-color: var(--brand); - } - - .voters :not(.vote-tooltip) { - overflow: hidden; - } - - .voters .choice-view * { - white-space: nowrap; - text-overflow: ellipsis; - } - - .voters .voter-name { - flex-grow: 1; - padding: 5px; - white-space:nowrap; - text-overflow:ellipsis; - } - - .voters .voter-avatar { - width: 24px; - min-width: 24px; - height: 24px; - margin: 2px 0; - font-size: 0.85em; - } - - .voters .row:hover .name { - background-color: var(--vote-hover); - border-bottom-color: var(--brand); - } - - .voters .name button { - margin-left: 3px; - overflow: visible; - } - - .voters .results, - .voters .choices { - display: flex; - width: 100%; - } - - .voters .result, .voters .choice { - min-width: 15px; - width: 100%; - height: 2em; - padding: 5px; - text-align: center; - white-space:nowrap; - text-overflow:ellipsis; - } - - .voters .row .ignored { - background: repeating-linear-gradient( - 45deg, - transparent, - transparent 10px, - var(--hatching) 10px, - var(--hatching) 20px); - } - - .voters .row:hover { - background-color: var(--vote-hover); - } - - .voters .row:hover .ignored { - background: repeating-linear-gradient( - 45deg, - var(--vote-hover), - var(--vote-hover) 10px, - var(--hatching) 10px, - var(--hatching) 20px); - } - - .voters .result.checkbox { - background-color: var(--vote-not-selected); - } - - .voters .result.checkbox.selected { - background-color: var(--vote-selected); - } - - .voters .vote-tooltip { - position: absolute; - padding: 10px; - color: var(--tooltip-color); - background: var(--tooltip-background); - border-radius: 5px; - box-shadow: 0px 0px 10px var(--shadow); - opacity: 0.8; - text-align: center; - z-index: 9999; - } - - .voters .vote-tooltip:after { - content: ''; - position: absolute; - bottom: 100%; - left: 50%; - margin-left: -8px; - width: 0; height: 0; - border-bottom: 8px solid var(--tooltip-background); - border-right: 8px solid transparent; - border-left: 8px solid transparent; - } - - .voters .vote-tooltip .vote-value { - margin-top: 5px; - font-weight: bold; - } - .warning-label { text-align: center; margin-top: 1em; diff --git a/pollen-ui-riot-js/src/main/web/tag/poll/VotesTable.tag.html b/pollen-ui-riot-js/src/main/web/tag/poll/VotesTable.tag.html new file mode 100644 index 00000000..5352e09e --- /dev/null +++ b/pollen-ui-riot-js/src/main/web/tag/poll/VotesTable.tag.html @@ -0,0 +1,346 @@ +<VotesTable> + <!-- Show votes --> + <div class="voters"> + <div class="row header separator-bottom"> + <div></div> + <div class="choices separator-left" if="{showChoiceHeader}"> + <div each="{choice in poll.choices}" class="choice separator-top separator-right" + onmouseenter="{parent.showTooltip(null, choice)}" onclick="{parent.showTooltip(null, choice)}" onmouseleave="{parent.hideTooltip}"> + <ChoiceView choice={choice} center="true" hideReport="true"></ChoiceView> + </div> + </div> + </div> + <LazyLoad pagination={pagination} onload={lazyLoad} load-size="20" not-load-on-start="true" ref="lazyLoad" class="elements"> + <yield to="element"> + <div class="row separator-bottom separator-right"> + <div class="name separator-left"> + <Avatar class="voter-avatar" avatar={element.voterAvatar} name={element.voterName} rounded="true"/> + <div class="voter-name" onmouseenter="{parent.parent.showTooltip(element)}" onclick="{parent.parent.showTooltip(vote)}" onmouseleave="{parent.parent.hideTooltip}"> + <span if="{!element.anonymous || element.permission}">{element.voterName}</span> + <span if="{element.anonymous && !element.permission}" class="anonymous-voter">{parent.parent.__.anonymousVoter}</span> + </div> + <button type="button" + class="c-button c-button--rounded u-xsmall c-button--brand" + if="{!parent.parent.poll.closed && element.permission}" + disabled="{parent.parent.voteInEdition != null || parent.parent.voting}" + onclick="{parent.parent.editVote(element)}"> + <i class="fa fa-pencil-square-o"></i> + </button> + <button type="button" + class="c-button c-button--rounded u-xsmall c-button--error" + if="{!parent.parent.poll.closed && (parent.parent.poll.permission || element.permission)}" + disabled="{parent.parent.voteInEdition != null || parent.parent.voting}" + onclick="{parent.parent.deleteVote(element)}"> + <i class="fa fa-trash"></i> + </button> + </div> + <div class="results separator-left {'ignored': element.ignored}" ref="results{index}"> + <div each="{choice in parent.parent.poll.choices}" + class="result separator-right {'checkbox' : parent.parent.pollTypeCheckbox} {'selected' : parent.parent.pollTypeCheckbox && parent.parent.poll.getVoteValue(element, choice) == 1}" + onmouseenter="{parent.parent.parent.showTooltip(element, choice)}" onclick="{parent.parent.parent.showTooltip(element, choice)}" onmouseleave="{parent.parent.parent.hideTooltip}"> + <span if="{!pollTypeCheckbox}">{parent.parent.parent.poll.getVoteValue(element, choice)}</span> + </div> + </div> + </div> + </yield> + <yield to="loading"> + <div class="row separator-bottom separator-right"> + <div class="name separator-left"> + <div class="voter-name"> + <i class="fa fa-user-circle c-icon"></i> + <i class="fa fa-spinner fa-pulse"></i> + </div> + </div> + <div class="results separator-left" ref="results{index}"> + <div each="{choice in parent.poll.choices}" + class="result separator-right"> + <i class="fa fa-spinner fa-pulse"></i> + </div> + </div> + </div> + </yield> + </LazyLoad> + <div class="vote-tooltip" ref="voteTooltip" show="{voteTooltip.show}"> + <ChoiceView if="{voteTooltip.choice}" + choice="{voteTooltip.choice}" center="true" hideReport="true"></ChoiceView> + <div class="vote-value" if="{!pollTypeCheckbox && voteTooltip.vote && voteTooltip.choice}"> + {voteTooltip.vote.ignored ? __.ignored :poll.getVoteValue(voteTooltip.vote, voteTooltip.choice)}</div> + <div if="{voteTooltip.vote && !voteTooltip.choice}">{voteTooltip.vote.voterName}</div> + </div> + </div> + + <script type="es6"> + const MIN_CHOICE_COLUMN_WIDTH = 100; + let session = require("../../js/Session"); + let Choice = require("../../js/Choice"); + this.moment = require("moment"); + this.installBundle(session, "poll_votes"); + this.showChoiceHeader = true; + this.voteTooltip = { + show: false, + choice: null, + vote: null + }; + + this.poll = require("../../js/Poll.js"); + + this.pagination = { + order: "topiaCreateDate", + desc: true + }; + + this.lazyLoad = pagination => { + return this.poll.loadLazyVotes(pagination).then((result) => { + return result; + }); + }; + + this.refresh = () => { + this.refs.lazyLoad && this.refs.lazyLoad.reload().then(() => { + this.updateShowChoiceContainer(); + this.update(); + }, () => {}); + }; + + this.updateShowChoiceContainer = () => { + let results0 = this.refs.lazyLoad && this.refs.lazyLoad.refs.results0; + this.showChoiceHeader = results0 && this.poll.choices && results0.offsetWidth / this.poll.choices.length >= MIN_CHOICE_COLUMN_WIDTH; + }; + + this.onPollChange = poll => { + this.poll = poll; + this.refresh(); + }; + + this.listen("poll", this.onPollChange); + this.listen("user", (user, oldUser) => { + if (user !== oldUser) { + this.refresh(); + this.update(); + } + }); + + this.editVote = (vote) => () => { + this.parent.refs.editVote.editVote(vote); + }; + + this.deleteVote = (vote) => (e) => { + e.preventDefault(); + e.stopPropagation(); + + this.confirm(this.__.delete).then((confirm) => { + if (confirm) { + this.voting = true; + this.update(); + + this.poll.deleteVote(vote).then(() => { + this.selectedChoiceNb = 0; + this.updateShowChoiceContainer(); + this.voting = false; + this.update(); + }, + (error) => { + this.voting = false; + this.error = error; + this.update(); + }); + } + }); + }; + + document.body.onresize = () => { + this.updateShowChoiceContainer(); + this.update(); + }; + + this.tooltipTimeout = null; + + this.showTooltip = (vote, choice) => (e) => { + e.preventDefault(); + e.stopPropagation(); + + this.tooltipTimeout = setTimeout(() => { + this.voteTooltip = { + choice: choice, + vote: vote, + show: choice || !vote || !vote.anonymous + }; + this.update(); + if (this.voteTooltip.show) { + let voteTooltip = this.refs.voteTooltip; + voteTooltip.style.top = (e.target.offsetTop + e.target.offsetHeight + 10) + "px"; + voteTooltip.style.left = (e.target.offsetLeft + (e.target.offsetWidth - voteTooltip.offsetWidth) / 2) + "px"; + } + }, 500); + }; + + this.hideTooltip = (e) => { + e.preventDefault(); + e.stopPropagation(); + clearTimeout(this.tooltipTimeout); + this.tooltipTimeout = null; + if (this.voteTooltip.show) { + this.voteTooltip = { + choice: null, + vote: null, + show: false + }; + this.update(); + } + }; + + </script> + <style> + + .voters { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + margin-top: 50px; + } + + .voters .elements, + .voters .loading { + width: 100%; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + } + + .voters .row { + display: flex; + width: 95%; + align-items: center; + } + + .voters .row > :first-child { + width: 200px; + min-width: 200px; + display: flex; + height: 2em; + padding: 0 5px; + } + + .voters .row:not(:first-child):hover { + border-bottom-color: var(--brand); + } + + .voters :not(.vote-tooltip) { + overflow: hidden; + } + + .voters .choice-view * { + white-space: nowrap; + text-overflow: ellipsis; + } + + .voters .voter-name { + flex-grow: 1; + padding: 5px; + white-space:nowrap; + text-overflow:ellipsis; + } + + .voters .voter-avatar { + width: 24px; + min-width: 24px; + height: 24px; + margin: 2px 0; + font-size: 0.85em; + } + + .voters .row:hover .name { + background-color: var(--vote-hover); + border-bottom-color: var(--brand); + } + + .voters .name button { + margin-left: 3px; + overflow: visible; + } + + .voters .results, + .voters .choices { + display: flex; + width: 100%; + } + + .voters .result, .voters .choice { + min-width: 15px; + width: 100%; + height: 2em; + padding: 5px; + text-align: center; + white-space:nowrap; + text-overflow:ellipsis; + } + + .voters .row .ignored { + background: repeating-linear-gradient( + 45deg, + transparent, + transparent 10px, + var(--hatching) 10px, + var(--hatching) 20px); + } + + .voters .row:hover { + background-color: var(--vote-hover); + } + + .voters .row:hover .ignored { + background: repeating-linear-gradient( + 45deg, + var(--vote-hover), + var(--vote-hover) 10px, + var(--hatching) 10px, + var(--hatching) 20px); + } + + .voters .result.checkbox { + background-color: var(--vote-not-selected); + } + + .voters .result.checkbox.selected { + background-color: var(--vote-selected); + } + + .voters .vote-tooltip { + position: absolute; + padding: 10px; + color: var(--tooltip-color); + background: var(--tooltip-background); + border-radius: 5px; + box-shadow: 0px 0px 10px var(--shadow); + opacity: 0.8; + text-align: center; + z-index: 9999; + } + + .voters .vote-tooltip:after { + content: ''; + position: absolute; + bottom: 100%; + left: 50%; + margin-left: -8px; + width: 0; height: 0; + border-bottom: 8px solid var(--tooltip-background); + border-right: 8px solid transparent; + border-left: 8px solid transparent; + } + + .voters .vote-tooltip .vote-value { + margin-top: 5px; + font-weight: bold; + } + + .warning-label { + text-align: center; + margin-top: 1em; + } + + </style> + +</VotesTable> -- To stop receiving notification emails like this one, please contact chorem.org SCM administrator <admin+scm@chorem.org>.
participants (1)
-
chorem.org scm