diff options
| author | Henry Jameson <me@hjkos.com> | 2019-07-28 13:30:29 +0300 |
|---|---|---|
| committer | Henry Jameson <me@hjkos.com> | 2019-07-28 13:30:29 +0300 |
| commit | b3aff9bbae77b2fd34b2267ce9196c0ebd3e4691 (patch) | |
| tree | 1219e00b6bfe6784add1578a3bc986c1dbb5f34d /src/components/poll/poll.js | |
| parent | 7f6f025792dcb3a10c94c8952d0312abd0b46989 (diff) | |
| parent | 4827e4d972f8ee11e606693e24ae4ca21711c6b1 (diff) | |
Merge remote-tracking branch 'upstream/develop' into emoji-selector-update
* upstream/develop: (469 commits)
Feature/add sticker picker
guard more secure routes
guard secure routes by redirecting to root
closest can returns itself as well
find inside status-content div only
try to use the closest a tag as target
Update es.json
Also apply keyword filter to subjects
Remove files I accidentally pushed in
fix issues caused by merges in usersearch on @
Add user search at
fix eslint warnings
remove vue-popperjs
fix moderation menu partially hidden by usercard boundary
migrate popper css
rewrite ModerationTools using v-tooltip
make popover position for status action dropdow relative to parent node
rewrite ExtraButtons using v-tooltip
install v-tooltip
i18n/Update pedantic Japanese translation
...
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 + }) + } + } +} |
