diff --git a/src/components/poll/poll.js b/src/components/poll/poll.js index 4598207b..e161a069 100644 --- a/src/components/poll/poll.js +++ b/src/components/poll/poll.js @@ -1,4 +1,5 @@ import Timeago from '../timeago/timeago.vue' +import { forEach } from 'lodash' export default { name: 'Poll', @@ -14,6 +15,7 @@ export default { }, created () { this.refreshInterval = setTimeout(this.refreshPoll, 30 * 1000) + this.multipleChoices = this.poll.options.map(_ => false) }, destroyed () { clearTimeout(this.refreshInterval) @@ -38,7 +40,7 @@ export default { }, choiceIndices () { return this.multipleChoices - .map((entry, index) => index) + .map((entry, index) => entry && index) .filter(value => typeof value === 'number') }, isDisabled () { @@ -55,7 +57,7 @@ export default { this.refreshInterval = setTimeout(this.refreshPoll, 30 * 1000) }, percentageForOption (count) { - return this.totalVotesCount === 0 ? 0 : Math.round((count + 5) / (this.totalVotesCount + 10) * 100) + return this.totalVotesCount === 0 ? 0 : Math.round(count / this.totalVotesCount * 100) }, resultTitle (option) { return `${option.votes_count}/${this.totalVotesCount} ${this.$t('polls.votes')}` @@ -63,6 +65,31 @@ export default { fetchPoll () { this.$store.dispatch('refreshPoll', { id: this.statusId, pollId: this.poll.id }) }, + activateOption (index) { + // forgive me father: doing checking the radio/checkboxes + // in code because of customized input elements need either + // a) an extra element for the actual graphic, or b) use a + // pseudo element for the label. We use b) which mandates + // using "for" and "id" matching which isn't nice when the + // same poll appears multiple times on the site (notifs and + // timeline for example). With code we can make sure it just + // works without altering the pseudo element implementation. + const clickedElement = this.$el.querySelector(`input[value="${index}"]`) + if (this.poll.multiple) { + // Checkboxes + const wasChecked = this.multipleChoices[index] + clickedElement.checked = !wasChecked + this.$set(this.multipleChoices, index, !wasChecked) + } else { + // Radio button + const allElements = this.$el.querySelectorAll('input') + forEach(allElements, element => { + element.checked = false + }) + clickedElement.checked = true + this.singleChoiceIndex = index + } + }, optionId (index) { return `poll${this.poll.id}-${index}` }, diff --git a/src/components/poll/poll.vue b/src/components/poll/poll.vue index ec1000c5..28e9f4a8 100644 --- a/src/components/poll/poll.vue +++ b/src/components/poll/poll.vue @@ -18,24 +18,20 @@ > -
+
-
@@ -54,7 +50,7 @@ {{totalVotesCount}} {{ $t("polls.votes") }} · 
- + @@ -80,6 +76,8 @@ display: flex; flex-direction: row; position: relative; + color: $fallback--lightText; + color: var(--lightText, $fallback--lightText); } .option-result-label { display: flex; @@ -94,7 +92,7 @@ height: 100%; position: absolute; background-color: $fallback--lightBg; - background-color: var(--faintLink, $fallback--lightBg); + background-color: var(--linkBg, $fallback--lightBg); border-radius: $fallback--panelRadius; border-radius: var(--panelRadius, $fallback--panelRadius); top: 0; diff --git a/src/components/poll/poll_form.js b/src/components/poll/poll_form.js new file mode 100644 index 00000000..6325adb0 --- /dev/null +++ b/src/components/poll/poll_form.js @@ -0,0 +1,74 @@ +export default { + name: 'PollForm', + props: ['visible'], + data: () => ({ + pollType: 'single', + options: ['', ''], + expiryAmount: 2, + expiryUnit: 'hours', + expiryUnits: ['minutes', 'hours', 'days'] + }), + computed: { + pollLimits () { + return this.$store.state.instance.pollLimits + }, + maxOptions () { + return this.pollLimits.max_options + }, + maxLength () { + return this.pollLimits.max_option_chars + } + }, + methods: { + clear () { + this.pollType = 'single' + this.options = ['', ''] + this.expiryAmount = 1 + this.expiryUnit = 'minutes' + }, + nextOption (index) { + const element = this.$el.querySelector(`#poll-${index+1}`) + if (element) { + element.focus() + } else { + // Try adding an option and try focusing on it + const addedOption = this.addOption() + if (addedOption) { + this.$nextTick(function () { + this.nextOption(index) + }) + } + } + }, + addOption () { + if (this.options.length < this.maxOptions) { + this.options.push('') + return true + } + return false + }, + deleteOption (index, event) { + if (this.options.length > 2) { + this.options.splice(index, 1) + } + }, + expiryAmountChange () { + this.expiryAmount = Math.max(1, this.expiryAmount) + this.expiryAmount = Math.min(120, this.expiryAmount) + this.updatePollToParent() + }, + updatePollToParent () { + const unitMultiplier = this.expiryUnit === 'minutes' ? 60 + : this.expiryUnit === 'hours' ? 60 * 60 + : 60 * 60 * 24 + + const expiresIn = this.expiryAmount * unitMultiplier + + this.$emit('update-poll', { + options: this.options, + multiple: this.pollType === 'multiple', + expiresIn + }) + } + } +} diff --git a/src/components/poll/poll_form/poll_form.vue b/src/components/poll/poll_form.vue similarity index 56% rename from src/components/poll/poll_form/poll_form.vue rename to src/components/poll/poll_form.vue index 77f97501..234be01f 100644 --- a/src/components/poll/poll_form/poll_form.vue +++ b/src/components/poll/poll_form.vue @@ -19,14 +19,14 @@ {{ $t("polls.add_option") }}
-
+