2025-03-13 02:10:20 +02:00
|
|
|
import Checkbox from 'components/checkbox/checkbox.vue'
|
2026-01-06 16:23:17 +02:00
|
|
|
import RichContent from 'components/rich_content/rich_content.jsx'
|
|
|
|
|
import Timeago from 'components/timeago/timeago.vue'
|
2025-02-03 13:02:14 +02:00
|
|
|
import { usePollsStore } from 'src/stores/polls'
|
2026-01-06 16:23:17 +02:00
|
|
|
import genRandomSeed from '../../services/random_seed/random_seed.service.js'
|
2019-06-18 20:28:31 +00:00
|
|
|
|
|
|
|
|
export default {
|
|
|
|
|
name: 'Poll',
|
2021-08-13 12:19:57 +03:00
|
|
|
props: ['basePoll', 'emoji'],
|
|
|
|
|
components: {
|
|
|
|
|
Timeago,
|
2025-03-13 02:10:20 +02:00
|
|
|
RichContent,
|
2026-01-06 16:22:52 +02:00
|
|
|
Checkbox,
|
2021-08-13 12:19:57 +03:00
|
|
|
},
|
2026-01-06 16:22:52 +02:00
|
|
|
data() {
|
2019-06-18 20:28:31 +00:00
|
|
|
return {
|
|
|
|
|
loading: false,
|
2023-02-18 13:40:42 -05:00
|
|
|
choices: [],
|
2026-01-06 16:22:52 +02:00
|
|
|
randomSeed: genRandomSeed(),
|
2019-06-18 20:28:31 +00:00
|
|
|
}
|
|
|
|
|
},
|
2026-01-06 16:22:52 +02:00
|
|
|
created() {
|
2023-04-05 22:30:20 -06:00
|
|
|
if (!usePollsStore().pollsObject[this.pollId]) {
|
|
|
|
|
usePollsStore().mergeOrAddPoll(this.basePoll)
|
2019-06-22 14:01:36 +00:00
|
|
|
}
|
2023-04-05 22:30:20 -06:00
|
|
|
usePollsStore().trackPoll(this.pollId)
|
2019-06-18 20:28:31 +00:00
|
|
|
},
|
2026-01-06 16:22:52 +02:00
|
|
|
unmounted() {
|
2023-04-05 22:30:20 -06:00
|
|
|
usePollsStore().untrackPoll(this.pollId)
|
2019-06-18 20:28:31 +00:00
|
|
|
},
|
|
|
|
|
computed: {
|
2026-01-06 16:22:52 +02:00
|
|
|
pollId() {
|
2019-06-22 14:01:36 +00:00
|
|
|
return this.basePoll.id
|
|
|
|
|
},
|
2026-01-06 16:22:52 +02:00
|
|
|
poll() {
|
2023-04-05 22:30:20 -06:00
|
|
|
const storePoll = usePollsStore().pollsObject[this.pollId]
|
2019-06-20 13:02:04 +00:00
|
|
|
return storePoll || {}
|
|
|
|
|
},
|
2026-01-06 16:22:52 +02:00
|
|
|
options() {
|
2019-06-20 13:02:04 +00:00
|
|
|
return (this.poll && this.poll.options) || []
|
|
|
|
|
},
|
2026-01-06 16:22:52 +02:00
|
|
|
expiresAt() {
|
2024-01-26 17:43:43 +09:00
|
|
|
return (this.poll && this.poll.expires_at) || null
|
2019-06-20 13:02:04 +00:00
|
|
|
},
|
2026-01-06 16:22:52 +02:00
|
|
|
expired() {
|
2019-06-22 14:01:36 +00:00
|
|
|
return (this.poll && this.poll.expired) || false
|
2019-06-18 20:28:31 +00:00
|
|
|
},
|
2026-01-06 16:22:52 +02:00
|
|
|
expirationLabel() {
|
2025-03-13 12:52:37 +02:00
|
|
|
if (this.$store.getters.mergedConfig.useAbsoluteTimeFormat) {
|
|
|
|
|
return this.expired ? 'polls.expired_at' : 'polls.expires_at'
|
|
|
|
|
} else {
|
|
|
|
|
return this.expired ? 'polls.expired' : 'polls.expires_in'
|
|
|
|
|
}
|
|
|
|
|
},
|
2026-01-06 16:22:52 +02:00
|
|
|
loggedIn() {
|
2019-06-18 20:28:31 +00:00
|
|
|
return this.$store.state.users.currentUser
|
|
|
|
|
},
|
2026-01-06 16:22:52 +02:00
|
|
|
showResults() {
|
2019-06-18 20:28:31 +00:00
|
|
|
return this.poll.voted || this.expired || !this.loggedIn
|
|
|
|
|
},
|
2026-01-06 16:22:52 +02:00
|
|
|
totalVotesCount() {
|
2019-06-18 20:28:31 +00:00
|
|
|
return this.poll.votes_count
|
|
|
|
|
},
|
2026-01-06 16:22:52 +02:00
|
|
|
containerClass() {
|
2019-06-18 20:28:31 +00:00
|
|
|
return {
|
2026-01-06 16:22:52 +02:00
|
|
|
loading: this.loading,
|
2019-06-18 20:28:31 +00:00
|
|
|
}
|
|
|
|
|
},
|
2026-01-06 16:22:52 +02:00
|
|
|
choiceIndices() {
|
2019-06-18 20:28:31 +00:00
|
|
|
// 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)
|
2026-01-06 16:22:52 +02:00
|
|
|
.filter((value) => typeof value === 'number')
|
2019-06-18 20:28:31 +00:00
|
|
|
},
|
2026-01-06 16:22:52 +02:00
|
|
|
isDisabled() {
|
2019-06-18 20:28:31 +00:00
|
|
|
const noChoice = this.choiceIndices.length === 0
|
|
|
|
|
return this.loading || noChoice
|
2026-01-06 16:22:52 +02:00
|
|
|
},
|
2019-06-18 20:28:31 +00:00
|
|
|
},
|
|
|
|
|
methods: {
|
2026-01-06 16:22:52 +02:00
|
|
|
percentageForOption(count) {
|
|
|
|
|
return this.totalVotesCount === 0
|
|
|
|
|
? 0
|
|
|
|
|
: Math.round((count / this.totalVotesCount) * 100)
|
2019-06-18 20:28:31 +00:00
|
|
|
},
|
2026-01-06 16:22:52 +02:00
|
|
|
resultTitle(option) {
|
2019-06-18 20:28:31 +00:00
|
|
|
return `${option.votes_count}/${this.totalVotesCount} ${this.$t('polls.votes')}`
|
|
|
|
|
},
|
2026-01-06 16:22:52 +02:00
|
|
|
activateOption(index, value) {
|
2025-03-13 02:10:20 +02:00
|
|
|
let result
|
2019-06-18 20:28:31 +00:00
|
|
|
if (this.poll.multiple) {
|
2025-03-13 02:10:20 +02:00
|
|
|
result = this.choices || this.options.map(() => false)
|
2019-06-18 20:28:31 +00:00
|
|
|
} else {
|
2025-03-13 02:10:20 +02:00
|
|
|
result = this.options.map(() => false)
|
2019-06-18 20:28:31 +00:00
|
|
|
}
|
2025-03-13 02:10:20 +02:00
|
|
|
result[index] = value
|
|
|
|
|
this.choices = result
|
2019-06-18 20:28:31 +00:00
|
|
|
},
|
2026-01-06 16:22:52 +02:00
|
|
|
optionId(index) {
|
2019-06-18 20:28:31 +00:00
|
|
|
return `poll${this.poll.id}-${index}`
|
|
|
|
|
},
|
2026-01-06 16:22:52 +02:00
|
|
|
vote() {
|
2019-06-18 20:28:31 +00:00
|
|
|
if (this.choiceIndices.length === 0) return
|
|
|
|
|
this.loading = true
|
2026-01-06 16:22:52 +02:00
|
|
|
usePollsStore()
|
|
|
|
|
.votePoll({
|
|
|
|
|
id: this.statusId,
|
|
|
|
|
pollId: this.poll.id,
|
|
|
|
|
choices: this.choiceIndices,
|
|
|
|
|
})
|
|
|
|
|
.then(() => {
|
|
|
|
|
this.loading = false
|
|
|
|
|
})
|
|
|
|
|
},
|
|
|
|
|
},
|
2019-06-20 13:02:04 +00:00
|
|
|
}
|