diff --git a/bundles/org.openhab.ui/web/src/assets/sitemap-lexer.nearley b/bundles/org.openhab.ui/web/src/assets/sitemap-lexer.nearley
index b413cd31f3..e8fd9ef8e4 100644
--- a/bundles/org.openhab.ui/web/src/assets/sitemap-lexer.nearley
+++ b/bundles/org.openhab.ui/web/src/assets/sitemap-lexer.nearley
@@ -2,32 +2,40 @@
const moo = require('moo')
let lexer = moo.compile({
- WS: /[ \t]+/,
- comment: /\/\/.*?$/,
- number: /\-?[0-9]+(?:\.[0-9]*)?/,
- string: { match: /"(?:\\["\\]|[^\n"\\])*"/, value: x => x.slice(1, -1) },
- sitemap: 'sitemap ',
- name: 'name=',
- label: 'label=',
- item: 'item=',
- icon: 'icon=',
- widgetattr: ['url=', 'refresh=', 'service=', 'refresh=', 'period=', 'legend=', 'height=', 'frequency=', 'sendFrequency=',
- 'switchEnabled=', 'mappings=', 'minValue=', 'maxValue=', 'step=', 'separator=', 'encoding='],
- nlwidget: ['Switch ', 'Selection ', 'Slider ', 'List ', 'Setpoint ', 'Video ', 'Chart ', 'Webview ', 'Colorpicker ', 'Mapview ', 'Default '],
- lwidget: ['Text', 'Group', 'Image', 'Frame'],
- identifier: /[A-Za-z0-9_]+/,
- lparen: '(',
- rparen: ')',
- colon: ':',
- lbrace: '{',
- rbrace: '}',
- lbracket: '[',
- rbracket: ']',
- lt: '<',
- gt: '>',
- equals: '=',
- comma: ',',
- NL: { match: /\n/, lineBreaks: true },
+ WS: /[ \t]+/,
+ comment: /\/\/.*?$/,
+ number: /\-?[0-9]+(?:\.[0-9]*)?/,
+ string: { match: /"(?:\\["\\]|[^\n"\\])*"/, value: x => x.slice(1, -1) },
+ sitemap: 'sitemap ',
+ name: 'name=',
+ label: 'label=',
+ item: 'item=',
+ icon: 'icon=',
+ widgetattr: ['url=', 'refresh=', 'service=', 'period=', 'legend=', 'height=', 'mappings=', 'minValue=', 'maxValue=', 'step=', 'separator=', 'encoding=', 'yAxisDecimalPattern='],
+ widgetfreqattr: 'sendFrequency=',
+ widgetfrcitmattr: 'forceasitem=',
+ widgetvisiattr: 'visibility=',
+ widgetcolorattr: ['labelcolor=', 'valuecolor=', 'iconcolor='],
+ widgetswitchattr: 'switchSupport',
+ nlwidget: ['Switch ', 'Selection ', 'Slider ', 'List ', 'Setpoint ', 'Video ', 'Chart ', 'Webview ', 'Colorpicker ', 'Mapview ', 'Default '],
+ lwidget: ['Text ', 'Group ', 'Image ', 'Frame '],
+ identifier: /[A-Za-z][A-Za-z0-9_]*/,
+ lparen: '(',
+ rparen: ')',
+ colon: ':',
+ lbrace: '{',
+ rbrace: '}',
+ lbracket: '[',
+ rbracket: ']',
+ eq: '==',
+ noteq: '!=',
+ lteq: '<=',
+ gteq: '>=',
+ lt: '<',
+ gt: '>',
+ equals: '=',
+ comma: ',',
+ NL: { match: /\n/, lineBreaks: true },
})
function getSitemap(d) {
@@ -64,7 +72,6 @@
@lexer lexer
-
Main -> _ Sitemap _ {% (d) => d[1] %}
Sitemap -> %sitemap _ SitemapName __ SitemapLabel __ %lbrace _ Widgets _ %rbrace {% getSitemap %}
@@ -77,23 +84,49 @@ Widgets -> Widget
Widget -> %nlwidget _ WidgetAttrs:* {% getWidget %}
| %lwidget _ WidgetAttrs:* {% getWidget %}
- | %lwidget _ WidgetAttrs:* __ %lbrace __ Widgets __ %rbrace {% getWidget %}
+ | %lwidget _ WidgetAttrs:* _ %lbrace _ Widgets _ %rbrace {% getWidget %}
WidgetAttrs -> WidgetAttr {% (d) => [d[0]] %}
| WidgetAttrs _ WidgetAttr {% (d) => d[0].concat([d[2]]) %}
-WidgetAttr -> WidgetAttrName WidgetAttrValue {% (d) => [d[0][0].value, d[1]] %}
+WidgetAttr -> %widgetswitchattr {% (d) => ['switchEnabled', true] %}
+ | %widgetfreqattr {% (d) => ['frequency', d[1]] %}
+ | %widgetfrcitmattr {% (d) => ['forceAsItem', d[1]] %}
+ | WidgetAttrName WidgetAttrValue {% (d) => [d[0][0].value, d[1]] %}
+ | WidgetVisibilityAttrName WidgetVisibilityAttrValue {% (d) => [d[0][0].value, d[1]] %}
+ | WidgetColorAttrName WidgetColorAttrValue {% (d) => [d[0][0].value, d[1]] %}
WidgetAttrName -> %item | %label | %icon | %widgetattr
WidgetAttrValue -> %string {% (d) => d[0].value %}
| %identifier {% (d) => d[0].value %}
| %number {% (d) => { return parseFloat(d[0].value) } %}
| %lbracket _ Mappings _ %rbracket {% (d) => d[2] %}
+WidgetVisibilityAttrName -> %widgetvisiattr
+WidgetVisibilityAttrValue -> %lbracket _ Visibilities _ %rbracket {% (d) => d[2] %}
+WidgetColorAttrName -> %widgetcolorattr
+WidgetColorAttrValue -> %lbracket _ Colors _ %rbracket {% (d) => d[2] %}
Mappings -> Mapping {% (d) => [d[0]] %}
| Mappings _ %comma _ Mapping {% (d) => d[0].concat([d[4]]) %}
-Mapping -> MappingCommand %equals MappingLabel {% (d) => d[0][0].value.toString() + '=' + d[2][0].value.toString() %}
+Mapping -> MappingCommand _ %equals _ MappingLabel {% (d) => d[0][0].value.toString() + '=' + d[4][0].value.toString() %}
MappingCommand -> %number | %identifier | %string
MappingLabel -> %number | %identifier | %string
+Visibilities -> Visibility {% (d) => [d[0]] %}
+ | Visibilities _ %comma _ Visibility {% (d) => d[0].concat([d[4]]) %}
+Visibility -> VisibilityCommand _ VisibilityComparator _ VisibilityValue {% (d) => d[0][0].value.toString() + d[2][0].value.toString() + d[4][0].value.toString() %}
+VisibilityCommand -> %identifier | %string
+VisibilityComparator -> %eq | %noteq | %lteq | %gteq | %lt | %gt
+VisibilityValue -> %number | %identifier | %string
+
+Colors -> Color {% (d) => [d[0]] %}
+ | Colors _ %comma _ Color {% (d) => d[0].concat([d[4]]) %}
+Color -> ColorCommand _ ColorComparator _ ColorValue _ %equals _ ColorName {% (d) => d[0][0].value.toString() + d[2][0].value.toString() + d[4][0].value.toString() + '=' + d[8][0].value.toString() %}
+ | ColorComparator _ ColorValue _ %equals _ ColorName {% (d) => d[0][0].value.toString() + d[2][0].value.toString() + '=' + d[6][0].value.toString() %}
+ | ColorValue _ %equals _ ColorName {% (d) => "==" + d[0][0].value.toString() + '=' + d[4][0].value.toString() %}
+ | ColorName {% (d) => d[0][0].value.toString() %}
+ColorCommand -> %identifier | %string
+ColorComparator -> %eq | %noteq | %lteq | %gteq | %lt | %gt
+ColorValue -> %number | %identifier | %string
+ColorName -> %identifier | %string
_ -> null {% () => null %}
| _ %WS {% () => null %}
diff --git a/bundles/org.openhab.ui/web/src/components/pagedesigner/sitemap/attribute-details.vue b/bundles/org.openhab.ui/web/src/components/pagedesigner/sitemap/attribute-details.vue
new file mode 100644
index 0000000000..fb25f00512
--- /dev/null
+++ b/bundles/org.openhab.ui/web/src/components/pagedesigner/sitemap/attribute-details.vue
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
+
+
+ Add
+
+
+
+
+
+
diff --git a/bundles/org.openhab.ui/web/src/components/pagedesigner/sitemap/dslUtil.js b/bundles/org.openhab.ui/web/src/components/pagedesigner/sitemap/dslUtil.js
index 8c15d4ef86..08a3fce2b4 100644
--- a/bundles/org.openhab.ui/web/src/components/pagedesigner/sitemap/dslUtil.js
+++ b/bundles/org.openhab.ui/web/src/components/pagedesigner/sitemap/dslUtil.js
@@ -4,18 +4,31 @@ function writeWidget (widget, indent) {
if (widget.config) {
for (let key in widget.config) {
if (!widget.config[key]) continue
- dsl += ` ${key}=`
- if (key === 'item' || Number.isFinite(widget.config[key])) {
- dsl += widget.config[key]
- } else if (key === 'mappings') {
- dsl += '['
- const mappingsDsl = widget.config.mappings.map((m) =>
- `${m.split('=')[0]}="${m.substring(m.indexOf('=') + 1)}"`
- )
- dsl += mappingsDsl.join(',')
- dsl += ']'
+ if ((Array.isArray(widget.config[key]) && widget.config[key].filter(Boolean).length <= 0)) continue
+ if (key === 'switchEnabled') {
+ dsl += ' switchSupport'
+ } else if (key === 'frequency') {
+ dsl += ' sendFrequency=' + widget.config[key]
+ } else if (key === 'forceAsItem') {
+ dsl += ' forceasitem=' + widget.config[key]
} else {
- dsl += '"' + widget.config[key] + '"'
+ dsl += ` ${key}=`
+ if (key === 'item' || Number.isFinite(widget.config[key])) {
+ dsl += widget.config[key]
+ } else if (['mappings', 'visibility', 'valuecolor', 'labelcolor', 'iconcolor'].includes(key)) {
+ dsl += '['
+ const arrayDsl = widget.config[key].map((v) => {
+ // Anything after the first comparator that is a string should be in quotes.
+ // Also quote string if no comparator (i.e. fixed labelcolor or valuecolor).
+ let value = v.substring(0, v.search(/[=<>]/))
+ value += v.substring(v.search(/[=<>]/)).replace(/"/g, '').replace(/[A-Za-z][A-Za-z0-9 _-]*/g, function (x) { return '"' + x.trim() + '"' })
+ return value.trim()
+ })
+ dsl += arrayDsl.filter(Boolean).join(',')
+ dsl += ']'
+ } else {
+ dsl += '"' + widget.config[key] + '"'
+ }
}
}
}
diff --git a/bundles/org.openhab.ui/web/src/components/pagedesigner/sitemap/mapping-details.vue b/bundles/org.openhab.ui/web/src/components/pagedesigner/sitemap/mapping-details.vue
deleted file mode 100644
index f2367dc28e..0000000000
--- a/bundles/org.openhab.ui/web/src/components/pagedesigner/sitemap/mapping-details.vue
+++ /dev/null
@@ -1,51 +0,0 @@
-
-
-
-
-
-
-
-
-
- Add
-
-
-
-
-
-
diff --git a/bundles/org.openhab.ui/web/src/components/pagedesigner/sitemap/widget-details.vue b/bundles/org.openhab.ui/web/src/components/pagedesigner/sitemap/widget-details.vue
index 46e81f614c..a4d2657dde 100644
--- a/bundles/org.openhab.ui/web/src/components/pagedesigner/sitemap/widget-details.vue
+++ b/bundles/org.openhab.ui/web/src/components/pagedesigner/sitemap/widget-details.vue
@@ -5,7 +5,7 @@
- widget.config.item = value" />
+ widget.config.item = value" />
@@ -23,14 +23,17 @@
-
+
+
+
+
@@ -67,13 +70,13 @@ export default {
additionalControls: {
Image: ['url', 'refresh'],
Video: ['url', 'encoding'],
- Chart: ['service', 'period', 'refresh', 'legend'],
+ Chart: ['service', 'period', 'refresh', 'legend', 'forceAsItem', 'yAxisDecimalPattern'],
Webview: ['url', 'height'],
Mapview: ['height'],
Slider: ['sendFrequency', 'switchEnabled', 'minValue', 'maxValue', 'step'],
List: ['separator'],
Setpoint: ['minValue', 'maxValue', 'step'],
- Colorpicker: ['frequency'],
+ Colorpicker: ['sendFrequency'],
Default: ['height']
}
}
diff --git a/bundles/org.openhab.ui/web/src/pages/settings/pages/sitemap/sitemap-edit.vue b/bundles/org.openhab.ui/web/src/pages/settings/pages/sitemap/sitemap-edit.vue
index d20e4db32c..8fb19b3a35 100644
--- a/bundles/org.openhab.ui/web/src/pages/settings/pages/sitemap/sitemap-edit.vue
+++ b/bundles/org.openhab.ui/web/src/pages/settings/pages/sitemap/sitemap-edit.vue
@@ -46,9 +46,25 @@
Nothing selected
+
+ Visibility
+
+
+
+ Label Color
+
+
+
+ Value Color
+
+
+
+ Icon Color
+
+
Mappings
-
+
Add Child Widget
@@ -101,8 +117,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
-
+
@@ -176,7 +204,7 @@