logo

pleroma-fe

My custom branche(s) on git.pleroma.social/pleroma/pleroma-fe git clone https://anongit.hacktivis.me/git/pleroma-fe.git/

poll.js (3633B)


  1. import Timeago from 'components/timeago/timeago.vue'
  2. import genRandomSeed from '../../services/random_seed/random_seed.service.js'
  3. import RichContent from 'components/rich_content/rich_content.jsx'
  4. import { forEach, map } from 'lodash'
  5. import { usePollsStore } from 'src/stores/polls'
  6. export default {
  7. name: 'Poll',
  8. props: ['basePoll', 'emoji'],
  9. components: {
  10. Timeago,
  11. RichContent
  12. },
  13. data () {
  14. return {
  15. loading: false,
  16. choices: [],
  17. randomSeed: genRandomSeed()
  18. }
  19. },
  20. created () {
  21. if (!usePollsStore().pollsObject[this.pollId]) {
  22. usePollsStore().mergeOrAddPoll(this.basePoll)
  23. }
  24. usePollsStore().trackPoll(this.pollId)
  25. },
  26. unmounted () {
  27. usePollsStore().untrackPoll(this.pollId)
  28. },
  29. computed: {
  30. pollId () {
  31. return this.basePoll.id
  32. },
  33. poll () {
  34. const storePoll = usePollsStore().pollsObject[this.pollId]
  35. return storePoll || {}
  36. },
  37. options () {
  38. return (this.poll && this.poll.options) || []
  39. },
  40. expiresAt () {
  41. return (this.poll && this.poll.expires_at) || null
  42. },
  43. expired () {
  44. return (this.poll && this.poll.expired) || false
  45. },
  46. loggedIn () {
  47. return this.$store.state.users.currentUser
  48. },
  49. showResults () {
  50. return this.poll.voted || this.expired || !this.loggedIn
  51. },
  52. totalVotesCount () {
  53. return this.poll.votes_count
  54. },
  55. containerClass () {
  56. return {
  57. loading: this.loading
  58. }
  59. },
  60. choiceIndices () {
  61. // Convert array of booleans into an array of indices of the
  62. // items that were 'true', so [true, false, false, true] becomes
  63. // [0, 3].
  64. return this.choices
  65. .map((entry, index) => entry && index)
  66. .filter(value => typeof value === 'number')
  67. },
  68. isDisabled () {
  69. const noChoice = this.choiceIndices.length === 0
  70. return this.loading || noChoice
  71. }
  72. },
  73. methods: {
  74. percentageForOption (count) {
  75. return this.totalVotesCount === 0 ? 0 : Math.round(count / this.totalVotesCount * 100)
  76. },
  77. resultTitle (option) {
  78. return `${option.votes_count}/${this.totalVotesCount} ${this.$t('polls.votes')}`
  79. },
  80. activateOption (index) {
  81. // forgive me father: doing checking the radio/checkboxes
  82. // in code because of customized input elements need either
  83. // a) an extra element for the actual graphic, or b) use a
  84. // pseudo element for the label. We use b) which mandates
  85. // using "for" and "id" matching which isn't nice when the
  86. // same poll appears multiple times on the site (notifs and
  87. // timeline for example). With code we can make sure it just
  88. // works without altering the pseudo element implementation.
  89. const allElements = this.$el.querySelectorAll('input')
  90. const clickedElement = this.$el.querySelector(`input[value="${index}"]`)
  91. if (this.poll.multiple) {
  92. // Checkboxes, toggle only the clicked one
  93. clickedElement.checked = !clickedElement.checked
  94. } else {
  95. // Radio button, uncheck everything and check the clicked one
  96. forEach(allElements, element => { element.checked = false })
  97. clickedElement.checked = true
  98. }
  99. this.choices = map(allElements, e => e.checked)
  100. },
  101. optionId (index) {
  102. return `poll${this.poll.id}-${index}`
  103. },
  104. vote () {
  105. if (this.choiceIndices.length === 0) return
  106. this.loading = true
  107. usePollsStore().votePoll(
  108. { id: this.statusId, pollId: this.poll.id, choices: this.choiceIndices }
  109. ).then(() => {
  110. this.loading = false
  111. })
  112. }
  113. }
  114. }