Skip to content

Commit

Permalink
Labelling of items in Model tab pages (Equipment & Properties) (#1264)
Browse files Browse the repository at this point in the history
Improve the relation display in model home cards.

For each Item part of the model, its parent path in model is parsed from API response and relations added to the item. Allows path label to be displayed in Equipment and Properties pages.

Signed-off-by: Gautier Taravella <tarag@mailbox.org>
Also-by: Yannick Schaus <github@schaus.net>
  • Loading branch information
tarag authored Jan 16, 2022
1 parent b6ebb6c commit 9533fdf
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 7 deletions.
6 changes: 6 additions & 0 deletions bundles/org.openhab.ui/web/src/components/cards/card-mixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,12 @@ export default {
}
},
methods: {
itemPathLabel (item) {
if (!item.modelPath) return '(?) > ' + item.name
return item.modelPath.map((parent) => {
return parent.label || parent.name
}).join(' > ')
},
cardOpening () {
this.cardId = this.title + '-' + this.$f7.utils.id()
history.pushState({ cardId: this.cardId }, null, window.location.href.split('#card=')[0] + '#' + this.$f7.utils.serializeObject({ card: this.element.key }))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,13 @@ export default {
},
computed: {
listContext () {
const standaloneEquipment = this.element.equipment.filter((i) => i.points.length === 0).map((i) => itemDefaultListComponent(i.item, true))
const standaloneEquipment = this.element.equipment.filter((i) => i.points.length === 0).map((i) => itemDefaultListComponent(i.item, this.itemPathLabel(i.item)))
const equipmentWithPoints = this.element.equipment.filter((i) => i.points.length !== 0).map((i) => {
return [
{
component: 'oh-list-item',
config: {
title: i.item.label || i.item.name,
title: [this.itemPathLabel(i.item), i.item.label || i.item.name].filter((label) => label && label.length > 0).join(' > '),
divider: true
}
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export default {
divider: true
}
},
...this.itemsByPointType[pointType].map((p) => itemDefaultListComponent(p, true))
...this.itemsByPointType[pointType].map((p) => itemDefaultListComponent(p, this.itemPathLabel(p)))
])
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
in the "listWidget" metadata namespace of the item
*/

export default function itemDefaultListComponent (item, itemNameAsFooter) {
export default function itemDefaultListComponent (item, itemNameAsFooterOrLocation) {
const stateDescription = item.stateDescription || {}
const metadata = (item.metadata && item.metadata.listWidget) ? item.metadata.listWidget : {}
let component = null
Expand Down Expand Up @@ -98,7 +98,8 @@ export default function itemDefaultListComponent (item, itemNameAsFooter) {
if (!component.config.title) component.config.title = item.label || item.name
if (item.category && !component.config.icon) component.config.icon = 'oh:' + item.category
if (item.category && ['Switch', 'Rollershutter', 'Contact', 'Dimmer', 'Group'].indexOf(item.type) >= 0) component.config.iconUseState = true
if (item.label && itemNameAsFooter) component.config.footer = item.name
if (item.label && itemNameAsFooterOrLocation === true) component.config.footer = item.name
else if (item.label && itemNameAsFooterOrLocation) component.config.footer = itemNameAsFooterOrLocation
if (!item.category) component.config.fallbackIconToInitial = true

return component
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<template>
<f7-list-button v-if="config.listButton && !context.editmode" :title="config.title || 'Action'" :color="config.color || 'blue'" @click="performAction" />
<f7-list-item divider :title="config.title" v-else-if="config.divider && !context.editmode" />
<f7-list-item divider ref="divider" :title="config.title" v-else-if="config.divider && !context.editmode" />
<f7-list-item v-else v-bind="config" :divider="config.divider && !context.editmode"
:media-item="context.parent.component.config.mediaList && !config.divider"
:badge="(config.divider) ? 'Divider' : (config.listButton) ? 'List button' : config.badge"
Expand All @@ -24,6 +24,12 @@
</f7-list-item>
</template>

<style lang="stylus">
.item-divider > span
flex-shrink 1
overflow hidden
</style>

<script>
import mixin from '../../widget-mixin'
import { actionsMixin } from '../../widget-actions'
Expand All @@ -32,6 +38,49 @@ import { OhListItemDefinition } from '@/assets/definitions/widgets/standard/list
export default {
name: 'oh-list-item',
mixins: [mixin, actionsMixin],
widget: OhListItemDefinition
widget: OhListItemDefinition,
mounted () {
mixin.mounted.call(this)
if (this.config.divider && !this.context.editmode) {
this.$nextTick(function () {
this.trimTitle()
})
}
},
created () {
if (this.config.divider && !this.context.editmode) {
window.addEventListener('resize', this.duringResize)
}
},
destroyed () {
window.removeEventListener('resize', this.duringResize)
if (this.timer) clearTimeout(this.timer)
},
methods: {
duringResize () {
if (this.timer) clearTimeout(this.timer)
this.timer = setTimeout(this.resized, 200)
},
resized () {
if (this.$refs.divider && this.$refs.divider.$el && this.$refs.divider.$el.firstChild) {
this.$refs.divider.$el.firstChild.textContent = this.config.title
}
this.trimTitle()
},
trimTitle () {
if (this.$refs.divider && this.$refs.divider.$el && this.$refs.divider.$el.firstChild) {
let element = this.$refs.divider.$el.firstChild
let trimCount = 0
if (element.scrollWidth > element.offsetWidth) {
let value = '' + element.textContent
do {
value = '' + value.substr(2)
trimCount++
element.textContent = value
} while (element.scrollWidth > element.offsetWidth && trimCount < 100)
}
}
}
}
}
</script>
21 changes: 21 additions & 0 deletions bundles/org.openhab.ui/web/src/pages/home/homecards-mixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,31 @@ export default {
}
}
},
// Recursively builds path in model (sorted array of relations to ancestors, either Equipment or Location) for an item
// that has semantics configuration and returns it
buildPathInModel (item) {
if (!item.metadata || !item.metadata.semantics) return
if (item.modelPath) return item.modelPath
// console.log(`Building path for ${item.name} with semantics ${item.metadata.semantics.config}`)
let parent = null
if (item.metadata.semantics.config && item.metadata.semantics.config.isPointOf) {
parent = (this.items.find((i) => i.name === item.metadata.semantics.config.isPointOf))
} else if (item.metadata.semantics.config && item.metadata.semantics.config.isPartOf) {
parent = (this.items.find((i) => i.name === item.metadata.semantics.config.isPartOf))
} else if (item.metadata.semantics.config && item.metadata.semantics.config.hasLocation) {
parent = (this.items.find((i) => i.name === item.metadata.semantics.config.hasLocation))
}
item.modelPath = parent ? [...this.buildPathInModel(parent), parent] : []
return item.modelPath
},
loadModel (page) {
this.$oh.api.get('/rest/items?metadata=semantics,listWidget,widgetOrder')
.then((data) => {
this.items = data
// build model path for all model items
data.forEach((item) => {
if (item.metadata && item.metadata.semantics) this.buildPathInModel(item)
})
// get the location items
const locations = data.filter((item, index, items) => {
return item.metadata && item.metadata.semantics &&
Expand Down

0 comments on commit 9533fdf

Please sign in to comment.