Handle polls in drafts

This commit is contained in:
tusooa 2023-03-10 20:16:03 -05:00
parent 4a044d067a
commit 5cddf18a4e
No known key found for this signature in database
GPG Key ID: 42AEC43D48433C51
4 changed files with 71 additions and 28 deletions

View File

@ -1,5 +1,5 @@
import * as DateUtils from 'src/services/date_utils/date_utils.js' import * as DateUtils from 'src/services/date_utils/date_utils.js'
import { uniq } from 'lodash' import { pollFallback } from 'src/services/poll/poll.service.js'
import { library } from '@fortawesome/fontawesome-svg-core' import { library } from '@fortawesome/fontawesome-svg-core'
import Select from '../select/select.vue' import Select from '../select/select.vue'
import { import {
@ -17,14 +17,31 @@ export default {
Select Select
}, },
name: 'PollForm', name: 'PollForm',
props: ['visible'], props: {
data: () => ({ visible: {},
pollType: 'single', modelValue: {
options: ['', ''], type: Object,
expiryAmount: 10, required: true
expiryUnit: 'minutes' }
}), },
emits: ['update:modelValue'],
computed: { computed: {
pollType: {
get () { return pollFallback(this.modelValue, 'pollType') },
set (newVal) { this.$emit('update:modelValue', { ...this.modelValue, pollType: newVal }) }
},
options: {
get () { return pollFallback(this.modelValue, 'options') },
set (newVal) { this.$emit('update:modelValue', { ...this.modelValue, options: newVal }) }
},
expiryAmount: {
get () { return pollFallback(this.modelValue, 'expiryAmount') },
set (newVal) { this.$emit('update:modelValue', { ...this.modelValue, expiryAmount: newVal }) }
},
expiryUnit: {
get () { return pollFallback(this.modelValue, 'expiryUnit') },
set (newVal) { this.$emit('update:modelValue', { ...this.modelValue, expiryUnit: newVal }) }
},
pollLimits () { pollLimits () {
return this.$store.state.instance.pollLimits return this.$store.state.instance.pollLimits
}, },
@ -107,21 +124,6 @@ export default {
this.updatePollToParent() this.updatePollToParent()
}, },
updatePollToParent () { updatePollToParent () {
const expiresIn = this.convertExpiryFromUnit(
this.expiryUnit,
this.expiryAmount
)
const options = uniq(this.options.filter(option => option !== ''))
if (options.length < 2) {
this.$emit('update-poll', { error: this.$t('polls.not_enough_options') })
return
}
this.$emit('update-poll', {
options,
multiple: this.pollType === 'multiple',
expiresIn
})
} }
} }
} }

View File

@ -9,6 +9,7 @@ import StatusContent from '../status_content/status_content.vue'
import fileTypeService from '../../services/file_type/file_type.service.js' import fileTypeService from '../../services/file_type/file_type.service.js'
import { findOffset } from '../../services/offset_finder/offset_finder.service.js' import { findOffset } from '../../services/offset_finder/offset_finder.service.js'
import { propsToNative } from '../../services/attributes_helper/attributes_helper.service.js' import { propsToNative } from '../../services/attributes_helper/attributes_helper.service.js'
import { pollFormToMasto } from 'src/services/poll/poll.service.js'
import { reject, map, uniqBy, debounce } from 'lodash' import { reject, map, uniqBy, debounce } from 'lodash'
import suggestor from '../emoji_input/suggestor.js' import suggestor from '../emoji_input/suggestor.js'
import { mapGetters, mapState } from 'vuex' import { mapGetters, mapState } from 'vuex'
@ -159,6 +160,7 @@ const PostStatusForm = {
nsfw: !!sensitiveByDefault, nsfw: !!sensitiveByDefault,
files: [], files: [],
poll: {}, poll: {},
hasPoll: false,
mediaDescriptions: {}, mediaDescriptions: {},
visibility: scope, visibility: scope,
contentType contentType
@ -174,6 +176,7 @@ const PostStatusForm = {
nsfw: this.statusIsSensitive || !!sensitiveByDefault, nsfw: this.statusIsSensitive || !!sensitiveByDefault,
files: this.statusFiles || [], files: this.statusFiles || [],
poll: this.statusPoll || {}, poll: this.statusPoll || {},
hasPoll: false,
mediaDescriptions: this.statusMediaDescriptions || {}, mediaDescriptions: this.statusMediaDescriptions || {},
visibility: this.statusScope || scope, visibility: this.statusScope || scope,
contentType: statusContentType contentType: statusContentType
@ -189,7 +192,6 @@ const PostStatusForm = {
highlighted: 0, highlighted: 0,
newStatus: statusParams, newStatus: statusParams,
caret: 0, caret: 0,
pollFormVisible: false,
showDropIcon: 'hide', showDropIcon: 'hide',
dropStopTimeout: null, dropStopTimeout: null,
preview: null, preview: null,
@ -290,6 +292,9 @@ const PostStatusForm = {
debouncedSaveDraft () { debouncedSaveDraft () {
return debounce(this.saveDraft, 3000) return debounce(this.saveDraft, 3000)
}, },
pollFormVisible () {
return this.newStatus.hasPoll
},
...mapGetters(['mergedConfig']), ...mapGetters(['mergedConfig']),
...mapState({ ...mapState({
mobileLayout: state => state.interface.mobileLayout mobileLayout: state => state.interface.mobileLayout
@ -323,9 +328,9 @@ const PostStatusForm = {
visibility: newStatus.visibility, visibility: newStatus.visibility,
contentType: newStatus.contentType, contentType: newStatus.contentType,
poll: {}, poll: {},
hasPoll: false,
mediaDescriptions: {} mediaDescriptions: {}
} }
this.pollFormVisible = false
this.$refs.mediaUpload && this.$refs.mediaUpload.clearFile() this.$refs.mediaUpload && this.$refs.mediaUpload.clearFile()
this.clearPollForm() this.clearPollForm()
if (this.preserveFocus) { if (this.preserveFocus) {
@ -355,7 +360,7 @@ const PostStatusForm = {
return return
} }
const poll = this.pollFormVisible ? this.newStatus.poll : {} const poll = this.newStatus.hasPoll ? pollFormToMasto(this.newStatus.poll) : {}
if (this.pollContentError) { if (this.pollContentError) {
this.error = this.pollContentError this.error = this.pollContentError
return return
@ -632,7 +637,7 @@ const PostStatusForm = {
this.newStatus.visibility = visibility this.newStatus.visibility = visibility
}, },
togglePollForm () { togglePollForm () {
this.pollFormVisible = !this.pollFormVisible this.newStatus.hasPoll = !this.newStatus.hasPoll
}, },
setPoll (poll) { setPoll (poll) {
this.newStatus.poll = poll this.newStatus.poll = poll

View File

@ -233,7 +233,7 @@
v-if="pollsAvailable" v-if="pollsAvailable"
ref="pollForm" ref="pollForm"
:visible="pollFormVisible" :visible="pollFormVisible"
@update-poll="setPoll" v-model="newStatus.poll"
/> />
<div <div
ref="bottom" ref="bottom"

View File

@ -0,0 +1,36 @@
import * as DateUtils from 'src/services/date_utils/date_utils.js'
import { uniq } from 'lodash'
const pollFallbackValues = {
pollType: 'single',
options: ['', ''],
expiryAmount: 10,
expiryUnit: 'minutes'
}
const pollFallback = (object, attr) => {
return object[attr] !== undefined ? object[attr] : pollFallbackValues[attr]
}
const pollFormToMasto = (poll) => {
const expiresIn = DateUtils.unitToSeconds(
pollFallback(poll, 'expiryUnit'),
pollFallback(poll, 'expiryAmount')
)
const options = uniq(pollFallback(poll, 'options').filter(option => option !== ''))
if (options.length < 2) {
return { errorKey: 'polls.not_enough_options' }
}
return {
options,
multiple: pollFallback(poll, 'pollType') === 'multiple',
expiresIn
}
}
export {
pollFallback,
pollFormToMasto
}