diff options
| author | Henry Jameson <me@hjkos.com> | 2019-08-31 22:38:02 +0300 |
|---|---|---|
| committer | Henry Jameson <me@hjkos.com> | 2019-08-31 22:38:02 +0300 |
| commit | 18ec13d796c0928d09fa93de4117822d2e35502c (patch) | |
| tree | 1cfb4d68a246c604396bb64bbba3e69bdf4fe511 /src/components/poll/poll.js | |
| parent | b3e9a5a71819c7d3a4b35c5b6ad551785a7ba44f (diff) | |
| parent | 018a650166a5dce0878b696359a999ab67634cfc (diff) | |
Merge remote-tracking branch 'upstream/develop' into docs
* upstream/develop: (193 commits)
fix user avatar fallback logic
remove dead code
make bio textarea resizable vertically only
remove dead code
remove dead code
fix crazy watch logic in conversation
show three dot button only if needed
hide mute conversation button to guests
update keyBy
generate idObj at timeline level
fix pin showing logic in conversation
Show a message when JS is disabled
Initialize chat only if user is logged in and it wasn't initialized before
i18n/Update Japanese
i18n/Update pedantic Japanese
sync profile tab state with location query
refactor TabSwitcher
use better name of controlled prop
fix potential bug to render active tab in controlled way
remove unused param
...
Diffstat (limited to 'src/components/poll/poll.js')
| -rw-r--r-- | src/components/poll/poll.js | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/src/components/poll/poll.js b/src/components/poll/poll.js new file mode 100644 index 00000000..98db5582 --- /dev/null +++ b/src/components/poll/poll.js @@ -0,0 +1,112 @@ +import Timeago from '../timeago/timeago.vue' +import { forEach, map } from 'lodash' + +export default { + name: 'Poll', + props: ['basePoll'], + components: { Timeago }, + data () { + return { + loading: false, + choices: [] + } + }, + created () { + if (!this.$store.state.polls.pollsObject[this.pollId]) { + this.$store.dispatch('mergeOrAddPoll', this.basePoll) + } + this.$store.dispatch('trackPoll', this.pollId) + }, + destroyed () { + this.$store.dispatch('untrackPoll', this.pollId) + }, + computed: { + pollId () { + return this.basePoll.id + }, + poll () { + const storePoll = this.$store.state.polls.pollsObject[this.pollId] + return storePoll || {} + }, + options () { + return (this.poll && this.poll.options) || [] + }, + expiresAt () { + return (this.poll && this.poll.expires_at) || 0 + }, + expired () { + return (this.poll && this.poll.expired) || false + }, + loggedIn () { + return this.$store.state.users.currentUser + }, + showResults () { + return this.poll.voted || this.expired || !this.loggedIn + }, + totalVotesCount () { + return this.poll.votes_count + }, + containerClass () { + return { + loading: this.loading + } + }, + choiceIndices () { + // Convert array of booleans into an array of indices of the + // items that were 'true', so [true, false, false, true] becomes + // [0, 3]. + return this.choices + .map((entry, index) => entry && index) + .filter(value => typeof value === 'number') + }, + isDisabled () { + const noChoice = this.choiceIndices.length === 0 + return this.loading || noChoice + } + }, + methods: { + percentageForOption (count) { + return this.totalVotesCount === 0 ? 0 : Math.round(count / this.totalVotesCount * 100) + }, + resultTitle (option) { + return `${option.votes_count}/${this.totalVotesCount} ${this.$t('polls.votes')}` + }, + 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 allElements = this.$el.querySelectorAll('input') + const clickedElement = this.$el.querySelector(`input[value="${index}"]`) + if (this.poll.multiple) { + // Checkboxes, toggle only the clicked one + clickedElement.checked = !clickedElement.checked + } else { + // Radio button, uncheck everything and check the clicked one + forEach(allElements, element => { element.checked = false }) + clickedElement.checked = true + } + this.choices = map(allElements, e => e.checked) + }, + optionId (index) { + return `poll${this.poll.id}-${index}` + }, + vote () { + if (this.choiceIndices.length === 0) return + this.loading = true + this.$store.dispatch( + 'votePoll', + { id: this.statusId, pollId: this.poll.id, choices: this.choiceIndices } + ).then(poll => { + this.loading = false + }) + } + } +} |
