Skip to content

Commit 27d797c

Browse files
committed
fixes and adding stateDescription min/max/step
Signed-off-by: Jimmy Tanagra <[email protected]>
1 parent 214c851 commit 27d797c

File tree

2 files changed

+51
-6
lines changed
  • bundles/org.openhab.ui/web/src

2 files changed

+51
-6
lines changed

bundles/org.openhab.ui/web/src/assets/definitions/widgets/system/input.js

+2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ export default () => [
1313
pb('validate-on-blur', 'Validate on blur', 'Only validate when focus moves away from input field'),
1414
pi('item', 'Item', 'Link the input value to the state of this item'),
1515
pb('useDisplayState', 'Use Display State', 'Use the formatted state as the value for the input control'),
16+
pd('min', 'Minimum', 'Minimum allowed value when type set to number'),
17+
pd('max', 'Maximum', 'Maximum allowed value when type set to number'),
1618
pd('step', 'Step', 'Step value when type set to number, any if left empty'),
1719
pb('showTime', 'Show time', 'Display time when type set to datepicker'),
1820
pt('defaultValue', 'Default value', 'Default value when not found in item state or variable'),

bundles/org.openhab.ui/web/src/components/widgets/system/oh-input.vue

+49-6
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ export default {
5656
widget: OhInputDefinition,
5757
data () {
5858
return {
59+
item: null,
5960
pendingUpdate: null
6061
}
6162
},
@@ -78,17 +79,32 @@ export default {
7879
} else if (this.config.item) {
7980
const item = this.context.store[this.config.item]
8081
if (item.state !== 'NULL' && item.state !== 'UNDEF' && item.state !== 'Invalid Date') {
81-
let value = this.config.useDisplayState ? item.displayState || item.state : item.state
82-
if (this.unit) {
83-
value = value.split(' ')[0]
84-
}
85-
return value
82+
const value = this.config.useDisplayState && item.displayState || item.state
83+
return this.config.type === 'number' ? this.extractValue(value) : value
8684
}
8785
}
8886
return this.config.defaultValue
8987
},
88+
// Returns the unit from the item's displayState, state description pattern or the item's unit symbol
9089
unit () {
91-
return this.config.type === 'number' && this.config.item && this.context.store[this.config.item].unit
90+
if (this.config.type !== 'number') return null
91+
if (!this.item?.unitSymbol) return null
92+
93+
const storeItem = this.context.store[this.config.item]
94+
// When the state of a dimensioned item is UNDEF/NULL, item.displayState is undefined
95+
// so we need to pull it out of the item's state description pattern
96+
if (this.config.useDisplayState) {
97+
const unit = this.extractUnit(storeItem.displayState || this.item.stateDescription?.pattern)
98+
return unit === '%unit%' ? this.item.unitSymbol : unit
99+
}
100+
return this.item.unitSymbol
101+
},
102+
// Returns the index of the last pattern in the stateDescription
103+
// Example: displayState = "Some label %0.1f footext °C", returns 2
104+
// Returns -1 if no pattern is found
105+
valueIndexInDisplayState () {
106+
const parts = this.item?.stateDescription?.pattern?.trim()?.split(/\s+/) || []
107+
return parts.findLastIndex(part => part.startsWith('%') && part !== '%unit%' && part !== '%%')
92108
},
93109
calendarParams () {
94110
if (this.config.type !== 'datepicker') return null
@@ -121,6 +137,18 @@ export default {
121137
}
122138
}
123139
},
140+
mounted () {
141+
if (this.config.item) {
142+
this.$oh.api.get(`/rest/items/${this.config.item}?recursive=false`).then((item) => {
143+
this.item = item
144+
if (this.config.useDisplayState) {
145+
this.config.min ||= item.stateDescription?.minimum
146+
this.config.max ||= item.stateDescription?.maximum
147+
this.config.step ||= item.stateDescription?.step
148+
}
149+
})
150+
}
151+
},
124152
methods: {
125153
updated (value) {
126154
if (this.config.type === 'texteditor') {
@@ -174,6 +202,21 @@ export default {
174202
this.$store.dispatch('sendCommand', { itemName: this.config.item, cmd })
175203
this.$set(this, 'pendingUpdate', null)
176204
}
205+
},
206+
extractUnit (pattern) {
207+
if (!pattern) return null
208+
return pattern.trim().split(/\s+/).pop()
209+
},
210+
extractValue (pattern) {
211+
if (!pattern) return null
212+
213+
const parts = pattern.trim().split(/\s+/)
214+
switch (parts.length) {
215+
case 0: return null
216+
case 1: return pattern
217+
case 2: return parts[0]
218+
default: return parts[this.valueIndexInDisplayState]
219+
}
177220
}
178221
}
179222
}

0 commit comments

Comments
 (0)