pleroma-fe/src/components/poll/poll.js
Henry Jameson cd4ad2df11 Merge remote-tracking branch 'origin/develop' into vue3-again
* origin/develop: (475 commits)
  Apply 1 suggestion(s) to 1 file(s)
  Update dependency @ungap/event-target to v0.2.3
  Update package.json
  fix broken icons after FA upgrade
  Update Font Awesome
  Update dependency webpack-dev-middleware to v3.7.3
  Update dependency vuelidate to v0.7.7
  Pin dependency @kazvmoe-infra/pinch-zoom-element to 1.2.0
  lint
  Make media modal buttons larger
  Add English translation for hide tooltip
  Add hide button to media modal
  Lint
  Prevent hiding media viewer if swiped over SwipeClick
  Fix webkit image blurs
  Fix video in media modal not displaying properly
  Add changelog for https://git.pleroma.social/pleroma/pleroma-fe/-/merge_requests/1403
  Remove image box-shadow in media modal
  Clean up debug code for image pinch zoom
  Bump @kazvmoe-infra/pinch-zoom-element to 1.2.0 on npm
  ...
2022-03-16 21:00:20 +02:00

117 lines
3.6 KiB
JavaScript

import Timeago from 'components/timeago/timeago.vue'
import RichContent from 'components/rich_content/rich_content.jsx'
import { forEach, map } from 'lodash'
export default {
name: 'Poll',
props: ['basePoll', 'emoji'],
components: {
Timeago,
RichContent
},
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)
},
unmounted () {
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
})
}
}
}