Fix #431 - validate rule modules config parameters (#451)

Allow config parameter controls based on smart select pickers
to display a validation message.

Signed-off-by: Yannick Schaus <github@schaus.net>
pull/452/head
Yannick Schaus 2020-10-26 11:23:37 +01:00 committed by GitHub
parent 179b41af83
commit d58606d623
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 49 additions and 24 deletions

View File

@ -116,4 +116,16 @@ export default {
color var(--f7-block-title-text-color) !important
.smart-select-popover.popover
--f7-popover-width 320px
.config-parameter
.smart-select
.input-invalid + .item-input-error-message
display block
max-width 80%
overflow hidden
text-overflow ellipsis
position relative
display block
white-space nowrap
margin-top 0
margin-bottom 0
</style>

View File

@ -1,7 +1,7 @@
<template>
<ul>
<f7-list-item :title="title" smart-select :smart-select-params="smartSelectParams" v-if="ready" ref="smartSelect">
<select :name="name" :multiple="multiple" @change="select">
<f7-list-item :title="title" smart-select :smart-select-params="smartSelectParams" v-if="ready" ref="smartSelect" class="item-picker">
<select :name="name" :multiple="multiple" @change="select" :required="required">
<option value="" v-if="!multiple"></option>
<option v-for="item in items" :value="item.name" :key="item.name" :selected="(multiple) ? Array.isArray(value) && value.indexOf(item.name) >= 0 : value === item.name">
{{item.label ? item.label + ' (' + item.name + ')' : item.name}}
@ -15,7 +15,7 @@
<script>
export default {
props: ['title', 'name', 'value', 'multiple', 'filterType'],
props: ['title', 'name', 'value', 'multiple', 'filterType', 'required'],
data () {
return {
ready: false,
@ -48,6 +48,7 @@ export default {
},
methods: {
select (e) {
this.$f7.input.validateInputs(this.$refs.smartSelect.$el)
const value = this.$refs.smartSelect.f7SmartSelect.getValue()
this.$emit('input', value)
}

View File

@ -1,5 +1,5 @@
<template>
<item-picker :title="configDescription.label || 'Item'" :value="value" @input="updateValue" :multiple="configDescription.multiple" />
<item-picker :title="configDescription.label || 'Item'" :value="value" @input="updateValue" :multiple="configDescription.multiple" :required="configDescription.required" />
</template>
<script>

View File

@ -2,7 +2,7 @@
<ul v-if="!inlineList">
<f7-list-item
:title="configDescription.label" smart-select :smart-select-params="smartSelectParams" ref="item">
<select :name="configDescription.name" @change="updateValue" :multiple="configDescription.multiple">
<select :name="configDescription.name" @change="updateValue" :multiple="configDescription.multiple" :required="configDescription.required">
<option v-if="!configDescription.required && !configDescription.multiple" :value="undefined" :selected="value === null || value === undefined"></option>
<option v-for="option in configDescription.options" :value="option.value" :key="option.value" :selected="isSelected(option)">{{option.label}}</option>
</select>
@ -65,6 +65,7 @@ export default {
},
methods: {
updateValue (evt) {
this.$f7.input.validateInputs(this.$refs.item.$el)
let value = (this.inlineList) ? evt : this.$refs.item.f7SmartSelect.getValue()
if (!this.configDescription.multiple && this.configDescription.type === 'INTEGER') {
value = parseInt(value)

View File

@ -2,7 +2,7 @@
<ul>
<f7-list-item
:title="configDescription.label" smart-select :smart-select-params="smartSelectParams" ref="item">
<select :name="configDescription.name" @change="updateValue" :multiple="configDescription.multiple">
<select :name="configDescription.name" @change="updateValue" :multiple="configDescription.multiple" :required="configDescription.required">
<option v-if="!configDescription.required" :value="undefined" :selected="value === null || value === undefined"></option>
<optgroup v-if="configDescription.context.indexOf('page') >= 0" label="Pages">
<option v-for="option in $store.getters.pages" :value="'page:' + option.uid" :key="option.uid" :selected="isSelected(option, 'page')">{{option.config.label}}</option>
@ -35,6 +35,7 @@ export default {
},
methods: {
updateValue (event) {
this.$f7.input.validateInputs(this.$refs.item.$el)
let value = this.$refs.item.f7SmartSelect.getValue()
if (!this.configDescription.multiple && this.configDescription.type === 'INTEGER') {
value = parseInt(value)

View File

@ -1,5 +1,5 @@
<template>
<rule-picker :title="configDescription.label" :value="value" @input="updateValue" :multiple="configDescription.multiple" />
<rule-picker :title="configDescription.label" :value="value" @input="updateValue" :multiple="configDescription.multiple" :required="configDescription.required" />
</template>
<script>

View File

@ -1,5 +1,5 @@
<template>
<thing-picker :title="configDescription.label" :value="value" @input="updateValue" :filter-uid="configDescription.options.map((o) => o.value)" />
<thing-picker :title="configDescription.label" :value="value" @input="updateValue" :filter-uid="configDescription.options.map((o) => o.value)" :multiple="configDescription.multiple" :required="configDescription.required" />
</template>
<script>

View File

@ -1,5 +1,5 @@
<template>
<trigger-channel-picker :title="configDescription.label" :value="value" @input="updateValue" />
<trigger-channel-picker :title="configDescription.label" :value="value" @input="updateValue" :multiple="configDescription.multiple" :required="configDescription.required" />
</template>
<script>

View File

@ -1,7 +1,7 @@
<template>
<ul>
<f7-list-item :title="title || 'Persistence Service'" smart-select :smart-select-params="smartSelectParams" v-if="ready">
<select :name="name" :multiple="multiple" @change="select">
<f7-list-item :title="title || 'Persistence Service'" smart-select :smart-select-params="smartSelectParams" v-if="ready" ref="smartSelect">
<select :name="name" :multiple="multiple" @change="select" :required="required">
<option value=""></option>
<option v-for="service in services" :value="service.id" :key="service.id" :selected="(multiple) ? value.indexOf(service.id) >= 0 : value === service.id">
{{service.label}}
@ -15,7 +15,7 @@
<script>
export default {
props: ['title', 'name', 'value', 'multiple'],
props: ['title', 'name', 'value', 'multiple', 'required'],
data () {
return {
ready: false,
@ -41,6 +41,7 @@ export default {
},
methods: {
select (e) {
this.$f7.input.validateInputs(this.$refs.smartSelect.$el)
this.$emit('input', e.target.value)
}
}

View File

@ -1,8 +1,8 @@
<template>
<ul>
<f7-list-item :title="title || 'Rule'" smart-select :smart-select-params="smartSelectParams" v-if="ready" ref="smartSelect">
<select :name="name" :multiple="multiple" @change="select">
<option value=""></option>
<select :name="name" :multiple="multiple" @change="select" :required="required">
<option v-if="!multiple" value=""></option>
<option v-for="rule in rules" :value="rule.uid" :key="rule.uid" :selected="(multiple) ? value && value.indexOf(rule.uid) >= 0 : value === rule.uid">
{{rule.name}}
</option>
@ -15,7 +15,7 @@
<script>
export default {
props: ['title', 'name', 'value', 'multiple'],
props: ['title', 'name', 'value', 'multiple', 'required'],
data () {
return {
ready: false,
@ -44,6 +44,7 @@ export default {
},
methods: {
select (e) {
this.$f7.input.validateInputs(this.$refs.smartSelect.$el)
const value = this.$refs.smartSelect.f7SmartSelect.getValue()
this.$emit('input', value)
}

View File

@ -1,8 +1,8 @@
<template>
<ul>
<f7-list-item :title="title || 'Thing'" smart-select :smart-select-params="smartSelectParams" v-if="ready">
<select :name="name" :multiple="multiple" @change="select">
<option value=""></option>
<f7-list-item :title="title || 'Thing'" smart-select :smart-select-params="smartSelectParams" ref="smartSelect" v-if="ready">
<select :name="name" :multiple="multiple" @change="select" :required="required">
<option v-if="!multiple" value=""></option>
<option v-for="thing in things" :value="thing.UID" :key="thing.UID" :selected="(multiple) ? value.indexOf(thing.UID) >= 0 : value === thing.UID">
{{thing.label}}
</option>
@ -15,7 +15,7 @@
<script>
export default {
props: ['title', 'name', 'value', 'multiple', 'filterType', 'filterUid'],
props: ['title', 'name', 'value', 'multiple', 'required', 'filterType', 'filterUid'],
data () {
return {
ready: false,
@ -55,6 +55,7 @@ export default {
},
methods: {
select (e) {
this.$f7.input.validateInputs(this.$refs.smartSelect.$el)
this.$emit('input', e.target.value)
}
}

View File

@ -1,8 +1,8 @@
<template>
<ul>
<f7-list-item :title="title || 'Thing'" smart-select :smart-select-params="smartSelectParams" v-if="ready">
<select :name="name" :multiple="multiple" @change="select">
<option value=""></option>
<f7-list-item :title="title || 'Thing'" smart-select :smart-select-params="smartSelectParams" v-if="ready" ref="smartSelect">
<select :name="name" :multiple="multiple" @change="select" :required="required">
<option v-if="!multiple" value=""></option>
<optgroup v-for="thing in things" :label="thing.label" :key="thing.UID">
<option v-for="channel in thing.triggerChannels" :value="channel.uid" :key="channel.uid" :selected="(multiple) ? value.indexOf(channel.uid) >= 0 : value === channel.uid">
{{channel.id}} ({{channel.label}})
@ -17,7 +17,7 @@
<script>
export default {
props: ['title', 'name', 'value', 'multiple', 'filterType'],
props: ['title', 'name', 'value', 'multiple', 'required', 'filterType'],
data () {
return {
ready: false,
@ -51,6 +51,7 @@ export default {
},
methods: {
select (e) {
this.$f7.input.validateInputs(this.$refs.smartSelect.$el)
this.$emit('input', e.target.value)
}
}

View File

@ -8,7 +8,7 @@
<f7-nav-title v-if="ruleModule && ruleModule.new">{{sectionLabels[currentSection][1]}}</f7-nav-title>
<f7-nav-title v-else>Edit module</f7-nav-title>
<f7-nav-right>
<f7-link v-show="currentRuleModuleType" @click="updateModuleConfig" class="popup-close">Done</f7-link>
<f7-link v-show="currentRuleModuleType" @click="updateModuleConfig">Done</f7-link>
</f7-nav-right>
</f7-navbar>
<f7-block v-if="ruleModule" class="no-margin no-padding">
@ -51,6 +51,7 @@
<f7-block-title v-if="ruleModule && currentRuleModuleType" style="margin-bottom: calc(var(--f7-block-title-margin-bottom) - var(--f7-list-margin-vertical))">Configuration</f7-block-title>
<f7-col v-if="ruleModule && currentRuleModuleType">
<config-sheet :key="currentSection + ruleModule.id"
ref="parameters"
:parameterGroups="[]"
:parameters="currentRuleModuleType.configDescriptions"
:configuration="ruleModule.configuration"
@ -94,7 +95,12 @@ export default {
this.$f7.emit('ruleModuleConfigClosed')
},
updateModuleConfig () {
if (!this.$refs.parameters.isValid()) {
this.$f7.dialog.alert('Please review the configuration and correct validation errors')
return
}
this.$f7.emit('ruleModuleConfigUpdate', this.ruleModule)
this.$refs.modulePopup.close()
},
groupedModuleTypes (section) {
const moduleTypes = this.moduleTypes[section].filter((t) => t.visibility === 'VISIBLE')