Widgets/config parameter fixes (#434)

Allow number config parameter control to input decimals
Fix #379: Check pattern if provided (fix #
Fix #391: Time of day parameter format
Fix #333: Decimal handling & FP issues with oh-stepper, oh-slider
+ fix parameter types, add unit parameter to oh-slider

Signed-off-by: Yannick Schaus <github@schaus.net>
pull/446/head
Yannick Schaus 2020-10-23 21:23:19 +02:00 committed by GitHub
parent ed342e4ae7
commit d9b0c09172
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 56 additions and 25 deletions

View File

@ -1,13 +1,14 @@
import { pi, pb, pn, pd } from '../helpers'
import { pi, pt, pb, pn, pd } from '../helpers'
export default () => [
pi('item', 'Item', 'Item to control'),
pn('min', 'Min', 'Minimum value'),
pn('max', 'Max', 'Maximum value'),
pd('min', 'Min', 'Minimum value'),
pd('max', 'Max', 'Maximum value'),
pd('step', 'Step', 'Minimum interval between values'),
pd('vertical', 'Vertical', 'Display the slider vertically'),
pb('label', 'Display Label', 'Display a label above the slider knob'),
pb('scale', 'Display Scale', 'Display a scale on the slider'),
pb('scaleSteps', 'Scale steps', 'Number of (major) scale markers'),
pb('scaleSubSteps', 'Scale sub-steps', 'Number of scale minor markers between each major marker')
pn('scaleSteps', 'Scale steps', 'Number of (major) scale markers'),
pn('scaleSubSteps', 'Scale sub-steps', 'Number of scale minor markers between each major marker'),
pt('unit', 'Unit', 'Text to append to the label while dragging the cursor')
]

View File

@ -2,8 +2,8 @@ import { pi, pb, pn, pd } from '../helpers'
export default () => [
pi('item', 'Item', 'Item to control'),
pn('min', 'Min', 'Minimum value'),
pn('max', 'Max', 'Maximum value'),
pd('min', 'Min', 'Minimum value'),
pd('max', 'Max', 'Maximum value'),
pd('step', 'Step', 'Minimum interval between values'),
pb('buttonsOnly', 'Buttons Only', 'Display the buttons without the value in the middle'),
pb('small', 'Small', 'Smaller size'),

View File

@ -17,7 +17,7 @@
// import ScriptEditorPopup from './config/script-editor-popup.vue'
import ParameterThing from './controls/parameter-thing.vue'
import ParameterBoolean from './controls/parameter-boolean.vue'
import ParameterInteger from './controls/parameter-integer.vue'
import ParameterNumber from './controls/parameter-number.vue'
import ParameterOptions from './controls/parameter-options.vue'
import ParameterItem from './controls/parameter-item.vue'
import ParameterScript from './controls/parameter-script.vue'
@ -51,8 +51,8 @@ export default {
const configDescription = this.configDescription
if (configDescription.options && configDescription.options.length && configDescription.limitToOptions && !configDescription.context) {
return ParameterOptions
} else if (configDescription.type === 'INTEGER') {
return ParameterInteger
} else if (configDescription.type === 'INTEGER' || configDescription.type === 'DECIMAL') {
return ParameterNumber
} else if (configDescription.type === 'BOOLEAN') {
return ParameterBoolean
} else if (configDescription.type === 'TEXT' && configDescription.context === 'script') {

View File

@ -6,7 +6,7 @@
:floating-label="$theme.md"
:min="configDescription.min"
:max="configDescription.max"
:step="configDescription.step"
:step="configDescription.step || (configDescription.type === 'DECIMAL') ? 0.01 : undefined"
:value="actualValue"
@input="updateValue"
:required="configDescription.required" validate
@ -20,12 +20,12 @@ export default {
props: ['configDescription', 'value'],
computed: {
actualValue () {
return parseInt(this.value)
return (this.configDescription.type === 'DECIMAL') ? parseFloat(this.value) : parseInt(this.value)
}
},
methods: {
updateValue (event) {
const value = parseInt(event.target.value)
const value = (this.configDescription.type === 'DECIMAL') ? parseFloat(event.target.value) : parseInt(event.target.value)
this.$emit('input', value)
}
}

View File

@ -7,6 +7,7 @@
:name="configDescription.name"
:value="value"
:autocomplete="autoCompleteOptions ? 'off' : ''"
:pattern="configDescription.pattern"
:required="configDescription.required" validate
:clear-button="!configDescription.required && configDescription.context !== 'password'"
@input="updateValue"

View File

@ -33,7 +33,7 @@ export default {
toolbar: false,
inputReadOnly: false,
rotateEffect: true,
value: (self.value && self.value.indexOf(':') >= 0) ? self.value.split(':') : ['0', '00'],
value: (self.value && self.value.indexOf(':') >= 0) ? self.value.split(':') : ['00', '00'],
formatValue: function (values, displayValues) {
return values[0] + ':' + values[1]
},
@ -42,7 +42,7 @@ export default {
{
values: (function () {
var arr = []
for (var i = 0; i <= 23; i++) { arr.push(i) }
for (var i = 0; i <= 23; i++) { arr.push(i < 10 ? `0${i}` : i) }
return arr
})()
},

View File

@ -1,5 +1,5 @@
<template>
<f7-list v-bind="config">
<f7-list v-bind="config" :title="null">
<f7-menu v-if="context.editmode" slot="before-list" class="configure-layout-menu margin-vertical padding-left">
<f7-menu-item @click="context.editmode.addWidget(context.component)" icon-f7="plus" />
<f7-menu-item style="margin-left: auto" icon-f7="square_list" dropdown>

View File

@ -1,7 +1,13 @@
<template>
<f7-range v-bind="config" :value="value" @range:changed="onChange" />
<f7-range class="oh-slider" v-bind="config" :value="value" @range:changed="onChange" :format-label="formatLabel" :format-scale-label="formatScaleLabel" />
</template>
<style lang="stylus">
.oh-slider
.range-knob-label
white-space nowrap
</style>
<script>
import mixin from '../widget-mixin'
import { OhSliderDefinition } from '@/assets/definitions/widgets/system'
@ -22,12 +28,25 @@ export default {
}
},
methods: {
formatLabel (value) {
return this.toStepFixed(value) + (this.config.unit || '')
},
formatScaleLabel (value) {
return this.toStepFixed(value)
},
toStepFixed (value) {
// uses the number of decimals in the step config to round the provided number
if (!this.config.step) return value
const nbDecimals = Number(this.config.step).toString().replace(',', '.').split('.')[1]
return parseFloat(Number(value).toFixed(nbDecimals))
},
onChange (value) {
if (value === this.value) return
const newValue = this.toStepFixed(value)
if (newValue === this.value) return
if (this.config.variable) {
this.$set(this.context.vars, this.config.variable, value)
} else if (this.config.item) {
this.$store.dispatch('sendCommand', { itemName: this.config.item, cmd: value.toString() })
this.$store.dispatch('sendCommand', { itemName: this.config.item, cmd: newValue.toString() })
}
}
}

View File

@ -1,6 +1,6 @@
<template>
<f7-stepper ref="stepper" v-bind="config" @stepper:change="onChange"
manual-input-mode />
:manual-input-mode="false" :format-value="formatValue" />
</template>
<script>
@ -16,23 +16,33 @@ export default {
computed: {
value () {
if (this.config.variable) return this.context.vars[this.config.variable]
const value = parseFloat(this.context.store[this.config.item].state)
const value = this.toStepFixed(parseFloat(this.context.store[this.config.item].state))
return value
}
},
watch: {
value (newValue) {
if (isNaN(newValue) || !isFinite(newValue)) return
this.$refs.stepper.setValue(newValue)
this.$refs.stepper.setValue(this.toStepFixed(newValue).toString())
}
},
methods: {
formatValue (value) {
return this.toStepFixed(value)
},
toStepFixed (value) {
// uses the number of decimals in the step config to round the provided number
if (!this.config.step) return value
const nbDecimals = Number(this.config.step).toString().replace(',', '.').split('.')[1]
return parseFloat(Number(value).toFixed(nbDecimals))
},
onChange (value) {
if (value === this.value) return
const newValue = this.toStepFixed(value)
if (newValue === this.value) return
if (this.config.variable) {
this.$set(this.context.vars, this.config.variable, value)
this.$set(this.context.vars, this.config.variable, newValue)
} else if (this.config.item) {
this.$store.dispatch('sendCommand', { itemName: this.config.item, cmd: value.toString() })
this.$store.dispatch('sendCommand', { itemName: this.config.item, cmd: newValue.toString() })
}
}
}