Skip to content

Commit

Permalink
Add missing sitemap attributes (#1487)
Browse files Browse the repository at this point in the history
Closes #324.

Signed-off-by: Mark Herwege <mark.herwege@telenet.be>
  • Loading branch information
mherwege authored Oct 8, 2022
1 parent 09adec5 commit 72fe51e
Show file tree
Hide file tree
Showing 6 changed files with 181 additions and 100 deletions.
93 changes: 63 additions & 30 deletions bundles/org.openhab.ui/web/src/assets/sitemap-lexer.nearley
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -64,7 +72,6 @@

@lexer lexer


Main -> _ Sitemap _ {% (d) => d[1] %}
Sitemap -> %sitemap _ SitemapName __ SitemapLabel __ %lbrace _ Widgets _ %rbrace {% getSitemap %}

Expand All @@ -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 %}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<template>
<f7-card v-if="widget">
<f7-card-content v-if="attributes.length">
<f7-list inline-labels sortable sortable-opposite sortable-enabled @sortable:sort="onSort">
<f7-list-input v-for="(attr, idx) in attributes" :key="attr.key"
type="text" :placeholder="placeholder" :value="attr.value" @change="updateAttribute(idx, $event)" clear-button />
</f7-list>
</f7-card-content>
<f7-card-footer key="item-card-buttons-edit-mode" v-if="widget.component !== 'Sitemap'">
<f7-button color="blue" @click="addAttribute">
Add
</f7-button>
</f7-card-footer>
</f7-card>
</template>

<script>
export default {
props: ['widget', 'attribute', 'placeholder'],
computed: {
attributes () {
if (this.widget && this.widget.config && this.widget.config[this.attribute]) {
return this.widget.config[this.attribute].map((attr, idx) => ({ key: idx + ': ' + attr, value: attr }))
}
return []
}
},
methods: {
updateAttribute (idx, $event) {
const value = $event.target.value
if (!value) {
this.widget.config[this.attribute].splice(idx, 1)
} else {
this.$set(this.widget.config[this.attribute], idx, value)
}
},
addAttribute () {
if (this.widget && this.widget.config && this.widget.config[this.attribute]) {
this.widget.config[this.attribute].push('')
} else {
this.$set(this.widget.config, this.attribute, [''])
}
},
onSort (ev) {
const element = this.widget.config[this.attribute][ev.from]
this.widget.config[this.attribute].splice(ev.from, 1)
this.widget.config[this.attribute].splice(ev.to, 0, element)
}
}
}
</script>
Original file line number Diff line number Diff line change
Expand Up @@ -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] + '"'
}
}
}
}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<f7-list-input v-if="widget.component === 'Sitemap'" label="ID" type="text" placeholder="ID" :value="widget.uid" @input="widget.uid = $event.target.value"
required validate pattern="[A-Za-z0-9_]+" error-message="Required. Alphanumeric &amp; underscores only" :disabled="!createMode" />
<f7-list-input label="Label" type="text" placeholder="Label" :value="widget.config.label" @input="updateParameter('label', $event)" clear-button />
<item-picker v-if="widget.component !== 'Sitemap'" title="Item" :value="widget.config.item" @input="(value) => widget.config.item = value" />
<item-picker v-if="widget.component !== 'Sitemap' && widget.component !== 'Frame'" title="Item" :value="widget.config.item" @input="(value) => widget.config.item = value" />
<ul v-if="widget.component !== 'Sitemap'">
<f7-list-input ref="icon" label="Icon" autocomplete="off" type="text" placeholder="temperature, firstfloor..." :value="widget.config.icon"
@input="updateParameter('icon', $event)" clear-button>
Expand All @@ -23,14 +23,17 @@
<f7-list-input v-if="supports('period')" label="Period" type="text" :value="widget.config.period" @input="updateParameter('period', $event)" clear-button />
<f7-list-input v-if="supports('height')" label="Height" type="number" :value="widget.config.height" @input="updateParameter('height', $event)" clear-button />
<f7-list-input v-if="supports('sendFrequency')" label="Frequency" type="text" :value="widget.config.sendFrequency" @input="updateParameter('sendFrequency', $event)" clear-button />
<f7-list-input v-if="supports('frequency')" label="Frequency" type="text" :value="widget.config.frequency" @input="updateParameter('frequency', $event)" clear-button />
<f7-list-input v-if="supports('minValue')" label="Minimum" type="number" :value="widget.config.minValue" @input="updateParameter('minValue', $event)" clear-button />
<f7-list-input v-if="supports('maxValue')" label="Maximum" type="number" :value="widget.config.maxValue" @input="updateParameter('maxValue', $event)" clear-button />
<f7-list-input v-if="supports('step')" label="Step" type="number" :value="widget.config.step" @input="updateParameter('step', $event)" clear-button />
<f7-list-input v-if="supports('separator')" label="Separator" type="text" :value="widget.config.separator" @input="updateParameter('separator', $event)" clear-button />
<f7-list-input v-if="supports('yAxisDecimalPattern')" label="Y-axis decimal pattern" type="text" :value="widget.config.separator" @input="updateParameter('yAxisDecimalPattern', $event)" clear-button />
<f7-list-item v-if="supports('switchEnabled')" title="Switch enabled">
<f7-toggle slot="after" :checked="widget.config.switchEnabled" @toggle:change="widget.config.switchEnabled = $event" />
</f7-list-item>
<f7-list-item v-if="supports('forceAsItem')" title="Force as item">
<f7-toggle slot="after" :checked="widget.config.forceAsItem" @toggle:change="widget.config.forceAsItem = $event" />
</f7-list-item>
</ul>
</f7-list>
</f7-card-content>
Expand Down Expand Up @@ -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']
}
}
Expand Down
Loading

0 comments on commit 72fe51e

Please sign in to comment.