logo

pleroma-fe

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

poll.js (3755B)


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