Move poll state handling to its own module
This commit is contained in:
parent
eca533aab6
commit
e5e9bb27f3
6 changed files with 96 additions and 34 deletions
|
@ -3,26 +3,33 @@ import { forEach, map } from 'lodash'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Poll',
|
name: 'Poll',
|
||||||
props: ['poll', 'statusId'],
|
props: ['pollId'],
|
||||||
components: { Timeago },
|
components: { Timeago },
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
loading: false,
|
loading: false,
|
||||||
choices: [],
|
choices: []
|
||||||
refreshInterval: null
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created () {
|
mounted () {
|
||||||
this.refreshInterval = setTimeout(this.refreshPoll, 30 * 1000)
|
this.$store.dispatch('trackPoll', this.pollId)
|
||||||
// Initialize choices to booleans and set its length to match options
|
|
||||||
this.choices = this.poll.options.map(_ => false)
|
|
||||||
},
|
},
|
||||||
destroyed () {
|
destroyed () {
|
||||||
clearTimeout(this.refreshInterval)
|
this.$store.dispatch('untrackPoll', this.pollId)
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
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 () {
|
expired () {
|
||||||
return Date.now() > Date.parse(this.poll.expires_at)
|
return Date.now() > Date.parse(this.expiresAt)
|
||||||
},
|
},
|
||||||
loggedIn () {
|
loggedIn () {
|
||||||
return this.$store.state.users.currentUser
|
return this.$store.state.users.currentUser
|
||||||
|
@ -33,9 +40,6 @@ export default {
|
||||||
totalVotesCount () {
|
totalVotesCount () {
|
||||||
return this.poll.votes_count
|
return this.poll.votes_count
|
||||||
},
|
},
|
||||||
expiresAt () {
|
|
||||||
return Date.parse(this.poll.expires_at).toLocaleString()
|
|
||||||
},
|
|
||||||
containerClass () {
|
containerClass () {
|
||||||
return {
|
return {
|
||||||
loading: this.loading
|
loading: this.loading
|
||||||
|
@ -55,11 +59,6 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
refreshPoll () {
|
|
||||||
if (this.expired) return
|
|
||||||
this.fetchPoll()
|
|
||||||
this.refreshInterval = setTimeout(this.refreshPoll, 30 * 1000)
|
|
||||||
},
|
|
||||||
percentageForOption (count) {
|
percentageForOption (count) {
|
||||||
return this.totalVotesCount === 0 ? 0 : Math.round(count / this.totalVotesCount * 100)
|
return this.totalVotesCount === 0 ? 0 : Math.round(count / this.totalVotesCount * 100)
|
||||||
},
|
},
|
||||||
|
@ -104,4 +103,4 @@ export default {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<div class="poll" v-bind:class="containerClass">
|
<div class="poll" v-bind:class="containerClass">
|
||||||
<div
|
<div
|
||||||
class="poll-option"
|
class="poll-option"
|
||||||
v-for="(option, index) in poll.options"
|
v-for="(option, index) in options"
|
||||||
:key="index"
|
:key="index"
|
||||||
>
|
>
|
||||||
<div v-if="showResults" :title="resultTitle(option)" class="option-result">
|
<div v-if="showResults" :title="resultTitle(option)" class="option-result">
|
||||||
|
@ -50,7 +50,7 @@
|
||||||
{{totalVotesCount}} {{ $t("polls.votes") }} ·
|
{{totalVotesCount}} {{ $t("polls.votes") }} ·
|
||||||
</div>
|
</div>
|
||||||
<i18n :path="expired ? 'polls.expired' : 'polls.expires_in'">
|
<i18n :path="expired ? 'polls.expired' : 'polls.expires_in'">
|
||||||
<Timeago :time="this.poll.expires_at" :auto-update="60" :now-threshold="0" />
|
<Timeago :time="this.expiresAt" :auto-update="60" :now-threshold="0" />
|
||||||
</i18n>
|
</i18n>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -124,7 +124,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="status.poll && status.poll.options">
|
<div v-if="status.poll && status.poll.options">
|
||||||
<poll :poll="status.poll" :status-id="status.id" />
|
<poll :poll-id="status.poll.id" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="status.attachments && (!hideSubjectStatus || showingLongSubject)" class="attachments media-body">
|
<div v-if="status.attachments && (!hideSubjectStatus || showingLongSubject)" class="attachments media-body">
|
||||||
|
|
|
@ -14,6 +14,7 @@ import authFlowModule from './modules/auth_flow.js'
|
||||||
import mediaViewerModule from './modules/media_viewer.js'
|
import mediaViewerModule from './modules/media_viewer.js'
|
||||||
import oauthTokensModule from './modules/oauth_tokens.js'
|
import oauthTokensModule from './modules/oauth_tokens.js'
|
||||||
import reportsModule from './modules/reports.js'
|
import reportsModule from './modules/reports.js'
|
||||||
|
import pollsModule from './modules/polls.js'
|
||||||
|
|
||||||
import VueI18n from 'vue-i18n'
|
import VueI18n from 'vue-i18n'
|
||||||
|
|
||||||
|
@ -72,7 +73,8 @@ const persistedStateOptions = {
|
||||||
authFlow: authFlowModule,
|
authFlow: authFlowModule,
|
||||||
mediaViewer: mediaViewerModule,
|
mediaViewer: mediaViewerModule,
|
||||||
oauthTokens: oauthTokensModule,
|
oauthTokens: oauthTokensModule,
|
||||||
reports: reportsModule
|
reports: reportsModule,
|
||||||
|
polls: pollsModule
|
||||||
},
|
},
|
||||||
plugins: [persistedState, pushNotifications],
|
plugins: [persistedState, pushNotifications],
|
||||||
strict: false // Socket modifies itself, let's ignore this for now.
|
strict: false // Socket modifies itself, let's ignore this for now.
|
||||||
|
|
73
src/modules/polls.js
Normal file
73
src/modules/polls.js
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
import { each, merge } from 'lodash'
|
||||||
|
import { set } from 'vue'
|
||||||
|
|
||||||
|
const polls = {
|
||||||
|
state: {
|
||||||
|
// Contains key = id, value = number of trackers for this poll
|
||||||
|
trackedPolls: {},
|
||||||
|
pollsObject: {}
|
||||||
|
},
|
||||||
|
mutations: {
|
||||||
|
addNewStatuses (state, { statuses }) {
|
||||||
|
each(statuses, status => {
|
||||||
|
if (status.poll) {
|
||||||
|
set(state.pollsObject, status.poll.id, status.poll)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
mergePoll (state, poll) {
|
||||||
|
state.pollsObject[poll.id] = merge(state.pollsObject[poll.id], poll)
|
||||||
|
},
|
||||||
|
trackPoll (state, pollId) {
|
||||||
|
const currentValue = state.trackedPolls[pollId]
|
||||||
|
if (currentValue) {
|
||||||
|
set(state.trackedPolls, pollId, currentValue + 1)
|
||||||
|
} else {
|
||||||
|
set(state.trackedPolls, pollId, 1)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
untrackPoll (state, pollId) {
|
||||||
|
const currentValue = state.trackedPolls[pollId]
|
||||||
|
if (currentValue) {
|
||||||
|
set(state.trackedPolls, pollId, currentValue - 1)
|
||||||
|
} else {
|
||||||
|
set(state.trackedPolls, pollId, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
actions: {
|
||||||
|
updatePoll ({ rootState, commit }, pollId) {
|
||||||
|
return rootState.api.backendInteractor.fetchPoll(pollId).then(poll => {
|
||||||
|
commit('mergePoll', poll)
|
||||||
|
return poll
|
||||||
|
})
|
||||||
|
},
|
||||||
|
updateTrackedPoll ({ rootState, dispatch, commit }, pollId) {
|
||||||
|
rootState.api.backendInteractor.fetchPoll(pollId).then(poll => {
|
||||||
|
setTimeout(() => {
|
||||||
|
if (rootState.polls.trackedPolls[pollId]) {
|
||||||
|
dispatch('updateTrackedPoll', pollId)
|
||||||
|
}
|
||||||
|
}, 30 * 1000)
|
||||||
|
commit('mergePoll', poll)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
trackPoll ({ rootState, commit, dispatch }, pollId) {
|
||||||
|
if (!rootState.polls.trackedPolls[pollId]) {
|
||||||
|
setTimeout(() => dispatch('updateTrackedPoll', pollId), 30 * 1000)
|
||||||
|
}
|
||||||
|
commit('trackPoll', pollId)
|
||||||
|
},
|
||||||
|
untrackPoll ({ commit }, pollId) {
|
||||||
|
commit('untrackPoll', pollId)
|
||||||
|
},
|
||||||
|
votePoll ({ rootState, commit }, { id, pollId, choices }) {
|
||||||
|
return rootState.api.backendInteractor.vote(pollId, choices).then(poll => {
|
||||||
|
commit('mergePoll', poll)
|
||||||
|
return poll
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default polls
|
|
@ -582,18 +582,6 @@ const statuses = {
|
||||||
]).then(([favoritedByUsers, rebloggedByUsers]) =>
|
]).then(([favoritedByUsers, rebloggedByUsers]) =>
|
||||||
commit('addFavsAndRepeats', { id, favoritedByUsers, rebloggedByUsers })
|
commit('addFavsAndRepeats', { id, favoritedByUsers, rebloggedByUsers })
|
||||||
)
|
)
|
||||||
},
|
|
||||||
votePoll ({ rootState, commit }, { id, pollId, choices }) {
|
|
||||||
return rootState.api.backendInteractor.vote(pollId, choices).then(poll => {
|
|
||||||
commit('updateStatusWithPoll', { id, poll })
|
|
||||||
return poll
|
|
||||||
})
|
|
||||||
},
|
|
||||||
refreshPoll ({ rootState, commit }, { id, pollId }) {
|
|
||||||
return rootState.api.backendInteractor.fetchPoll(pollId).then(poll => {
|
|
||||||
commit('updateStatusWithPoll', { id, poll })
|
|
||||||
return poll
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mutations
|
mutations
|
||||||
|
|
Loading…
Reference in a new issue