make min/max expiry dynamic

This commit is contained in:
shpuld 2019-06-17 21:13:24 +03:00
parent 32dae8eb7a
commit 64737f32d2
5 changed files with 73 additions and 26 deletions

View File

@ -194,13 +194,12 @@ const getNodeInfo = async ({ store }) => {
if (res.ok) { if (res.ok) {
const data = await res.json() const data = await res.json()
const metadata = data.metadata const metadata = data.metadata
store.dispatch('setInstanceOption', { name: 'pollLimits', value: metadata.pollLimits })
const features = metadata.features const features = metadata.features
store.dispatch('setInstanceOption', { name: 'mediaProxyAvailable', value: features.includes('media_proxy') }) store.dispatch('setInstanceOption', { name: 'mediaProxyAvailable', value: features.includes('media_proxy') })
store.dispatch('setInstanceOption', { name: 'chatAvailable', value: features.includes('chat') }) store.dispatch('setInstanceOption', { name: 'chatAvailable', value: features.includes('chat') })
store.dispatch('setInstanceOption', { name: 'gopherAvailable', value: features.includes('gopher') }) store.dispatch('setInstanceOption', { name: 'gopherAvailable', value: features.includes('gopher') })
store.dispatch('setInstanceOption', { name: 'pollsAvailable', value: features.includes('polls') }) store.dispatch('setInstanceOption', { name: 'pollsAvailable', value: features.includes('polls') })
store.dispatch('setInstanceOption', { name: 'pollLimits', value: metadata.pollLimits })
store.dispatch('setInstanceOption', { name: 'restrictedNicknames', value: metadata.restrictedNicknames }) store.dispatch('setInstanceOption', { name: 'restrictedNicknames', value: metadata.restrictedNicknames })
store.dispatch('setInstanceOption', { name: 'postFormats', value: metadata.postFormats }) store.dispatch('setInstanceOption', { name: 'postFormats', value: metadata.postFormats })

View File

@ -13,7 +13,8 @@
<style> <style>
.media-upload { .media-upload {
font-size: 26px; font-size: 26px;
flex: 1; min-width: 50px;
flex: 0;
} }
.icon-upload { .icon-upload {

View File

@ -1,12 +1,13 @@
import * as DateUtils from 'src/services/date_utils/date_utils.js'
export default { export default {
name: 'PollForm', name: 'PollForm',
props: ['visible'], props: ['visible'],
data: () => ({ data: () => ({
pollType: 'single', pollType: 'single',
options: ['', ''], options: ['', ''],
expiryAmount: 2, expiryAmount: 10,
expiryUnit: 'hours', expiryUnit: 'minutes'
expiryUnits: ['minutes', 'hours', 'days']
}), }),
computed: { computed: {
pollLimits () { pollLimits () {
@ -17,17 +18,40 @@ export default {
}, },
maxLength () { maxLength () {
return this.pollLimits.max_option_chars return this.pollLimits.max_option_chars
},
expiryUnits () {
const allUnits = ['minutes', 'hours', 'days']
const expiry = this.convertExpiryFromUnit
return allUnits.filter(
unit => this.pollLimits.max_expiration >= expiry(unit, 1)
)
},
minExpirationInCurrentUnit () {
return Math.ceil(
this.convertExpiryToUnit(
this.expiryUnit,
this.pollLimits.min_expiration
)
)
},
maxExpirationInCurrentUnit () {
return Math.floor(
this.convertExpiryToUnit(
this.expiryUnit,
this.pollLimits.max_expiration
)
)
} }
}, },
methods: { methods: {
clear () { clear () {
this.pollType = 'single' this.pollType = 'single'
this.options = ['', ''] this.options = ['', '']
this.expiryAmount = 1 this.expiryAmount = 10
this.expiryUnit = 'minutes' this.expiryUnit = 'minutes'
}, },
nextOption (index) { nextOption (index) {
const element = this.$el.querySelector(`#poll-${index+1}`) const element = this.$el.querySelector(`#poll-${index + 1}`)
if (element) { if (element) {
element.focus() element.focus()
} else { } else {
@ -52,17 +76,34 @@ export default {
this.options.splice(index, 1) this.options.splice(index, 1)
} }
}, },
convertExpiryToUnit (unit, amount) {
// Note: we want seconds and not milliseconds
switch (unit) {
case 'minutes': return (1000 * amount) / DateUtils.MINUTE
case 'hours': return (1000 * amount) / DateUtils.HOUR
case 'days': return (1000 * amount) / DateUtils.DAY
}
},
convertExpiryFromUnit (unit, amount) {
// Note: we want seconds and not milliseconds
switch (unit) {
case 'minutes': return 0.001 * amount * DateUtils.MINUTE
case 'hours': return 0.001 * amount * DateUtils.HOUR
case 'days': return 0.001 * amount * DateUtils.DAY
}
},
expiryAmountChange () { expiryAmountChange () {
this.expiryAmount = Math.max(1, this.expiryAmount) this.expiryAmount =
this.expiryAmount = Math.min(120, this.expiryAmount) Math.max(this.minExpirationInCurrentUnit, this.expiryAmount)
this.expiryAmount =
Math.min(this.maxExpirationInCurrentUnit, this.expiryAmount)
this.updatePollToParent() this.updatePollToParent()
}, },
updatePollToParent () { updatePollToParent () {
const unitMultiplier = this.expiryUnit === 'minutes' ? 60 const expiresIn = this.convertExpiryFromUnit(
: this.expiryUnit === 'hours' ? 60 * 60 this.expiryUnit,
: 60 * 60 * 24 this.expiryAmount
)
const expiresIn = this.expiryAmount * unitMultiplier
this.$emit('update-poll', { this.$emit('update-poll', {
options: this.options, options: this.options,

View File

@ -39,13 +39,16 @@
<input <input
type="number" type="number"
class="expiry-amount hide-number-spinner" class="expiry-amount hide-number-spinner"
min="1" :min="minExpirationInCurrentUnit"
max="120" :max="maxExpirationInCurrentUnit"
v-model="expiryAmount" v-model="expiryAmount"
@change="expiryAmountChange" @change="expiryAmountChange"
> >
<label class="expiry-unit select"> <label class="expiry-unit select">
<select v-model="expiryUnit" @change="updatePollToParent"> <select
v-model="expiryUnit"
@change="expiryAmountChange"
>
<option v-for="unit in expiryUnits" :value="unit"> <option v-for="unit in expiryUnits" :value="unit">
{{ $t(`time.${unit}_short`, ['']) }} {{ $t(`time.${unit}_short`, ['']) }}
</option> </option>
@ -83,12 +86,14 @@
.input-container { .input-container {
width: 100%; width: 100%;
input { input {
// Hack: dodge the floating X icon
padding-right: 2.5em;
width: 100%; width: 100%;
} }
} }
.icon-container { .icon-container {
// Move the icon over the input box // Hack: Move the icon over the input box
width: 2em; width: 2em;
margin-left: -2em; margin-left: -2em;
z-index: 1; z-index: 1;

View File

@ -7,13 +7,13 @@ import fileTypeService from '../../services/file_type/file_type.service.js'
import Completion from '../../services/completion/completion.js' import Completion from '../../services/completion/completion.js'
import { take, filter, reject, map, uniqBy } from 'lodash' import { take, filter, reject, map, uniqBy } from 'lodash'
const buildMentionsString = ({user, attentions}, currentUser) => { const buildMentionsString = ({ user, attentions }, currentUser) => {
let allAttentions = [...attentions] let allAttentions = [...attentions]
allAttentions.unshift(user) allAttentions.unshift(user)
allAttentions = uniqBy(allAttentions, 'id') allAttentions = uniqBy(allAttentions, 'id')
allAttentions = reject(allAttentions, {id: currentUser.id}) allAttentions = reject(allAttentions, { id: currentUser.id })
let mentions = map(allAttentions, (attention) => { let mentions = map(allAttentions, (attention) => {
return `@${attention.screen_name}` return `@${attention.screen_name}`
@ -98,7 +98,7 @@ const PostStatusForm = {
return false return false
} }
// eslint-disable-next-line camelcase // eslint-disable-next-line camelcase
return map(take(matchedUsers, 5), ({screen_name, name, profile_image_url_original}, index) => ({ return map(take(matchedUsers, 5), ({ screen_name, name, profile_image_url_original }, index) => ({
// eslint-disable-next-line camelcase // eslint-disable-next-line camelcase
screen_name: `@${screen_name}`, screen_name: `@${screen_name}`,
name: name, name: name,
@ -111,7 +111,7 @@ const PostStatusForm = {
if (matchedEmoji.length <= 0) { if (matchedEmoji.length <= 0) {
return false return false
} }
return map(take(matchedEmoji, 5), ({shortcode, image_url, utf}, index) => ({ return map(take(matchedEmoji, 5), ({ shortcode, image_url, utf }, index) => ({
screen_name: `:${shortcode}:`, screen_name: `:${shortcode}:`,
name: '', name: '',
utf: utf || '', utf: utf || '',
@ -188,7 +188,8 @@ const PostStatusForm = {
return this.$store.state.instance.safeDM return this.$store.state.instance.safeDM
}, },
pollsAvailable () { pollsAvailable () {
return this.$store.state.instance.pollsAvailable return this.$store.state.instance.pollsAvailable &&
this.$store.state.instance.pollLimits.max_options >= 2
}, },
hideScopeNotice () { hideScopeNotice () {
return this.$store.state.config.hideScopeNotice return this.$store.state.config.hideScopeNotice
@ -243,7 +244,7 @@ const PostStatusForm = {
onKeydown (e) { onKeydown (e) {
e.stopPropagation() e.stopPropagation()
}, },
setCaret ({target: {selectionStart}}) { setCaret ({ target: { selectionStart } }) {
this.caret = selectionStart this.caret = selectionStart
}, },
postStatus (newStatus) { postStatus (newStatus) {
@ -330,7 +331,7 @@ const PostStatusForm = {
}, },
fileDrop (e) { fileDrop (e) {
if (e.dataTransfer.files.length > 0) { if (e.dataTransfer.files.length > 0) {
e.preventDefault() // allow dropping text like before e.preventDefault() // allow dropping text like before
this.dropFiles = e.dataTransfer.files this.dropFiles = e.dataTransfer.files
} }
}, },