Fix icons not displayed & not dynamic on all pages (#1849)

Fixes #1839.
Fixes #574.
Closes #1860.

* Fixes Item icon styling on the Item detail page.
* Add support for openHAB iconsets.
* Fix `oh:` icons not properly displayed in `default-list-item.vue`.
* Refactor `oh-icon` config & style binding.
* Enable real-time state on the semantic model page.
* Enable state for the channel link edit page.
* Enable dynamic icons in the settings where missing and possible
(semantic model page, channel link edit page, Item edit page when
setting category, Items list page).
* Enable dynamic icons in the default list widget for most Items except
some and update the docs accordingly.
* Add a refresh button to the Item list page.

--
Signed-off-by: Florian Hotze <florianh_dev@icloud.com>
pull/1850/head
Florian Hotze 2023-05-02 22:58:13 +02:00 committed by GitHub
parent 79fbc793e3
commit 095bb2f9cb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 88 additions and 58 deletions

View File

@ -56,7 +56,7 @@ Display a color picker in a list
</PropBlock>
<PropBlock type="BOOLEAN" name="iconUseState" label="Icon depends on state">
<PropDescription>
Use the state of the item to get a dynamic icon (for openHAB icons only)
Use the state of the Item to get a dynamic icon (enabled by default for all Item types except <code>Call</code>, <code>Image</code> & <code>Location</code>) (for openHAB icons only)
</PropDescription>
</PropBlock>
</PropGroup>

View File

@ -56,7 +56,7 @@ Display an input field in a list
</PropBlock>
<PropBlock type="BOOLEAN" name="iconUseState" label="Icon depends on state">
<PropDescription>
Use the state of the item to get a dynamic icon (for openHAB icons only)
Use the state of the Item to get a dynamic icon (enabled by default for all Item types except <code>Call</code>, <code>Image</code> & <code>Location</code>) (for openHAB icons only)
</PropDescription>
</PropBlock>
</PropGroup>

View File

@ -421,7 +421,7 @@ Display the state of an item in a card
</PropBlock>
<PropBlock type="BOOLEAN" name="iconUseState" label="Icon depends on state">
<PropDescription>
Use the state of the item to get a dynamic icon (for openHAB icons only)
Use the state of the Item to get a dynamic icon (enabled by default for all Item types except <code>Call</code>, <code>Image</code> & <code>Location</code>) (for openHAB icons only)
</PropDescription>
</PropBlock>
<PropBlock type="BOOLEAN" name="vertical" label="Vertical arrangement">

View File

@ -67,7 +67,7 @@ Display the state of an item in a list
</PropBlock>
<PropBlock type="BOOLEAN" name="iconUseState" label="Icon depends on state">
<PropDescription>
Use the state of the item to get a dynamic icon (for openHAB icons only)
Use the state of the Item to get a dynamic icon (enabled by default for all Item types except <code>Call</code>, <code>Image</code> & <code>Location</code>) (for openHAB icons only)
</PropDescription>
</PropBlock>
</PropGroup>

View File

@ -56,7 +56,7 @@ A list item
</PropBlock>
<PropBlock type="BOOLEAN" name="iconUseState" label="Icon depends on state">
<PropDescription>
Use the state of the item to get a dynamic icon (for openHAB icons only)
Use the state of the Item to get a dynamic icon (enabled by default for all Item types except <code>Call</code>, <code>Image</code> & <code>Location</code>) (for openHAB icons only)
</PropDescription>
</PropBlock>
</PropGroup>

View File

@ -62,7 +62,7 @@ A marker on a floor plan
</PropBlock>
<PropBlock type="BOOLEAN" name="iconUseState" label="Icon depends on state">
<PropDescription>
Use the state of the item to get a dynamic icon (for openHAB icons only)
Use the state of the Item to get a dynamic icon (enabled by default for all Item types except <code>Call</code>, <code>Image</code> & <code>Location</code>) (for openHAB icons only)
</PropDescription>
</PropBlock>
<PropBlock type="INTEGER" name="iconSize" label="Icon Size">

View File

@ -56,7 +56,7 @@ Display player controls in a list
</PropBlock>
<PropBlock type="BOOLEAN" name="iconUseState" label="Icon depends on state">
<PropDescription>
Use the state of the item to get a dynamic icon (for openHAB icons only)
Use the state of the Item to get a dynamic icon (enabled by default for all Item types except <code>Call</code>, <code>Image</code> & <code>Location</code>) (for openHAB icons only)
</PropDescription>
</PropBlock>
</PropGroup>

View File

@ -56,7 +56,7 @@ Display rollershutter controls in a list
</PropBlock>
<PropBlock type="BOOLEAN" name="iconUseState" label="Icon depends on state">
<PropDescription>
Use the state of the item to get a dynamic icon (for openHAB icons only)
Use the state of the Item to get a dynamic icon (enabled by default for all Item types except <code>Call</code>, <code>Image</code> & <code>Location</code>) (for openHAB icons only)
</PropDescription>
</PropBlock>
</PropGroup>

View File

@ -56,7 +56,7 @@ Display a slider control in a list
</PropBlock>
<PropBlock type="BOOLEAN" name="iconUseState" label="Icon depends on state">
<PropDescription>
Use the state of the item to get a dynamic icon (for openHAB icons only)
Use the state of the Item to get a dynamic icon (enabled by default for all Item types except <code>Call</code>, <code>Image</code> & <code>Location</code>) (for openHAB icons only)
</PropDescription>
</PropBlock>
</PropGroup>

View File

@ -56,7 +56,7 @@ Display a stepper control in a list
</PropBlock>
<PropBlock type="BOOLEAN" name="iconUseState" label="Icon depends on state">
<PropDescription>
Use the state of the item to get a dynamic icon (for openHAB icons only)
Use the state of the Item to get a dynamic icon (enabled by default for all Item types except <code>Call</code>, <code>Image</code> & <code>Location</code>) (for openHAB icons only)
</PropDescription>
</PropBlock>
</PropGroup>

View File

@ -56,7 +56,7 @@ Display a toggle switch in a list
</PropBlock>
<PropBlock type="BOOLEAN" name="iconUseState" label="Icon depends on state">
<PropDescription>
Use the state of the item to get a dynamic icon (for openHAB icons only)
Use the state of the Item to get a dynamic icon (enabled by default for all Item types except <code>Call</code>, <code>Image</code> & <code>Location</code>) (for openHAB icons only)
</PropDescription>
</PropBlock>
</PropGroup>

View File

@ -34,7 +34,7 @@ export const OhPlanMarkerDefinition = () => new WidgetDefinition('oh-plan-marker
])
.paramGroup(pg('icon', 'Icon', 'You can customize the styles further with CSS attributes in the <code>iconStyle</code> parameter (in YAML only)'), [
pt('icon', 'Icon', 'Use <code>oh:iconName</code> (<a class="external text-color-blue" target="_blank" href="https://www.openhab.org/link/icons">openHAB icon</a>), <code>f7:iconName</code> (<a class="external text-color-blue" target="_blank" href="https://framework7.io/icons/">Framework7 icon</a>), <code>material:iconName</code> (<a class="external text-color-blue" target="_blank" href="https://jossef.github.io/material-design-icons-iconfont/">Material icon</a>) or <code>iconify:iconSet:iconName</code> (<a class="external text-color-blue" target="_blank" href="https://icon-sets.iconify.design">Iconify icon</a>, requires being online if not in cache)'),
pb('iconUseState', 'Icon depends on state', 'Use the state of the item to get a dynamic icon (for openHAB icons only)'),
pb('iconUseState', 'Icon depends on state', 'Use the state of the Item to get a dynamic icon (enabled by default for all Item types except <code>Call</code>, <code>Image</code> & <code>Location</code>) (for openHAB icons only)').a(),
pn('iconSize', 'Icon Size', 'Size of the icon in pixels (40 by default)'),
pn('iconWidth', 'Icon Width', 'Width of the icon in pixels (for openHAB icons only, 40 by default)').a(),
pn('iconHeight', 'Icon Height', 'Height of the icon in pixels (for openHAB icons only, 40 by default)').a(),

View File

@ -28,7 +28,7 @@ export const OhLabelCardDefinition = () => new WidgetDefinition('oh-label-card',
pt('icon', 'Icon', 'Use <code>oh:iconName</code> (<a class="external text-color-blue" target="_blank" href="https://www.openhab.org/link/icons">openHAB icon</a>), <code>f7:iconName</code> (<a class="external text-color-blue" target="_blank" href="https://framework7.io/icons/">Framework7 icon</a>), <code>material:iconName</code> (<a class="external text-color-blue" target="_blank" href="https://jossef.github.io/material-design-icons-iconfont/">Material icon</a>) or <code>iconify:iconSet:iconName</code> (<a class="external text-color-blue" target="_blank" href="https://icon-sets.iconify.design">Iconify icon</a>, requires being online if not in cache)'),
pt('iconColor', 'Icon Color', 'Not applicable to openHAB icons').a(),
pn('iconSize', 'Icon Size', 'Size of the icon in px').a(),
pb('iconUseState', 'Icon depends on state', 'Use the state of the item to get a dynamic icon (for openHAB icons only)').a(),
pb('iconUseState', 'Icon depends on state', 'Use the state of the Item to get a dynamic icon (enabled by default for all Item types except <code>Call</code>, <code>Image</code> & <code>Location</code>) (for openHAB icons only)').a(),
pb('vertical', 'Vertical arrangement', 'Display label below icon')
])
.paramGroup(pg('trend', 'Trend Line', 'Show a trend line in the background'), TrendParameters())

View File

@ -11,7 +11,7 @@ export const ListItemParameters = () => [
pt('after', 'After', 'Text to display on the opposite side of the item (set either this or a badge)').a(),
pt('icon', 'Icon', 'Use <code>oh:iconName</code> (<a class="external text-color-blue" target="_blank" href="https://www.openhab.org/link/icons">openHAB icon</a>), <code>f7:iconName</code> (<a class="external text-color-blue" target="_blank" href="https://framework7.io/icons/">Framework7 icon</a>), <code>material:iconName</code> (<a class="external text-color-blue" target="_blank" href="https://jossef.github.io/material-design-icons-iconfont/">Material icon</a>) or <code>iconify:iconSet:iconName</code> (<a class="external text-color-blue" target="_blank" href="https://icon-sets.iconify.design">Iconify icon</a>, requires being online if not in cache)'),
pt('iconColor', 'Icon Color', 'Not applicable to openHAB icons').a(),
pb('iconUseState', 'Icon depends on state', 'Use the state of the item to get a dynamic icon (for openHAB icons only)').a()
pb('iconUseState', 'Icon depends on state', 'Use the state of the Item to get a dynamic icon (enabled by default for all Item types except <code>Call</code>, <code>Image</code> & <code>Location</code>) (for openHAB icons only)').a()
]
// OhListItem

View File

@ -2,9 +2,9 @@
<div v-if="item" class="quick-link-form no-padding">
<f7-list inline-labels no-hairlines-md>
<f7-list-input label="Name" type="text" placeholder="Required" :value="item.name"
:disabled="!enableName" :info="(enableName) ? 'Note: cannot be changed after the creation' : ''"
:disabled="!createMode" :info="(createMode) ? 'Note: cannot be changed after the creation' : ''"
required :error-message="nameErrorMessage" :error-message-force="!!nameErrorMessage"
@input="onNameInput" :clear-button="enableName" />
@input="onNameInput" :clear-button="createMode" />
<f7-list-input label="Label" type="text" placeholder="Label" :value="item.label"
@input="item.label = $event.target.value" clear-button />
<f7-list-item v-if="item.type && !hideType" title="Type" type="text" smart-select :smart-select-params="{searchbar: true, openIn: 'popup', closeOnSelect: true}">
@ -24,7 +24,7 @@
<f7-list-input v-if="!hideCategory" ref="category" label="Category" autocomplete="off" type="text" placeholder="temperature, firstfloor..." :value="item.category"
@input="item.category = $event.target.value" clear-button>
<div slot="root-end" style="margin-left: calc(35% + 8px)">
<oh-icon :icon="item.category" height="32" width="32" />
<oh-icon :icon="item.category" :state="(createMode) ? null : item.state" height="32" width="32" />
</div>
</f7-list-input>
</f7-list>
@ -46,7 +46,7 @@ import * as Types from '@/assets/item-types.js'
import { Categories } from '@/assets/categories.js'
export default {
props: ['item', 'items', 'enableName', 'hideCategory', 'hideType', 'hideSemantics', 'forceSemantics'],
props: ['item', 'items', 'createMode', 'hideCategory', 'hideType', 'hideSemantics', 'forceSemantics'],
components: {
SemanticsPicker
},
@ -91,7 +91,7 @@ export default {
mounted () {
if (!this.item) return
if (!this.item.category) this.$set(this.item, 'category', '')
if (this.enableName) {
if (this.createMode) {
if (!this.items) this.items = []
this.validateName(this.item.name)
}

View File

@ -8,7 +8,7 @@
:subtitle="getItemTypeAndMetaLabel(item)"
:after="state"
v-on="$listeners">
<oh-icon v-if="!noIcon && item.category" slot="media" :icon="item.category" height="32" width="32" />
<oh-icon v-if="!noIcon && item.category" slot="media" :icon="item.category" :state="(noState) ? null : (context && context.store) ? context.store[item.name].state : item.state" height="32" width="32" />
<span v-else-if="!noIcon" slot="media" class="item-initial">{{ item.name[0] }}</span>
<f7-icon v-if="!item.editable && !ignoreEditable" slot="after-title" f7="lock_fill" size="1rem" color="gray" />
<slot name="footer" #footer />

View File

@ -3,7 +3,7 @@
<item-state-preview v-if="model.item.created !== false" :item="model.item" :context="context" :key="$utils.id()" />
<f7-block-title>Item</f7-block-title>
<item-details :model="model" :links="links" :items="items" @item-updated="$emit('item-updated')" @item-created="$emit('item-created')" @item-removed="$emit('item-removed')" @cancel-create="$emit('cancel-create')" />
<item-details :model="model" :links="links" :items="items" :context="context" @item-updated="$emit('item-updated')" @item-created="$emit('item-created')" @item-removed="$emit('item-removed')" @cancel-create="$emit('cancel-create')" />
<f7-block-title v-if="model.item.created !== false">
Metadata
</f7-block-title>

View File

@ -3,7 +3,7 @@
<f7-card-content>
<f7-list media-list accordion-list>
<ul>
<item v-if="!createMode" :item="model.item" :link="'/settings/items/' + model.item.name" :no-state="true" />
<item v-if="!createMode" :item="model.item" :link="'/settings/items/' + model.item.name" :context="context" />
<!-- <f7-list-button v-if="!editMode && !createMode" color="blue" title="Edit Item" @click="editMode = true">Edit Item</f7-list-button> -->
</ul>
</f7-list>
@ -12,7 +12,7 @@
<item-form :item="editedItem" :hide-type="true" :force-semantics="forceSemantics" />
</div>
<div class="padding-top" v-else-if="createMode">
<item-form :item="editedItem" :items="items" :enable-name="true" :force-semantics="forceSemantics" />
<item-form :item="editedItem" :items="items" :createMode="true" :force-semantics="forceSemantics" />
</div>
</f7-card-content>
<f7-card-footer v-if="createMode || editMode" key="item-card-buttons">
@ -42,7 +42,7 @@ import Item from '@/components/item/item.vue'
import ItemForm from '@/components/item/item-form.vue'
export default {
props: ['model', 'links', 'items'],
props: ['model', 'links', 'items', 'context'],
components: {
Item,
ItemForm

View File

@ -34,7 +34,7 @@
:footer="(link.item.label) ? link.item.name : '\xa0'"
:subtitle="getItemTypeAndMetaLabel(link.item)"
:after="context.store[link.item.name] ? context.store[link.item.name].displayState || context.store[link.item.name].state : link.item.state">
<oh-icon v-if="link.item.category" slot="media" :icon="link.item.category" height="32" width="32" />
<oh-icon v-if="link.item.category" slot="media" :icon="link.item.category" :state="context.store[link.item.name] ? context.store[link.item.name].state : link.item.state" height="32" width="32" />
<span v-else slot="media" class="item-initial">{{ link.item.name[0] }}</span>
<f7-icon v-if="!link.item.editable" slot="after-title" f7="lock_fill" size="1rem" color="gray" />
<!-- <f7-button slot="after-start" color="blue" icon-f7="compose" icon-size="24px" :link="`${item.name}/edit`"></f7-button> -->

View File

@ -48,7 +48,7 @@
@channel-updated="(e) => $emit('channels-updated', e)" />
</template>
<template #default="{ channel }" v-else-if="multipleLinksMode">
<item-form v-if="isChecked(channel)" :item="newItem(channel)" :items="items" :enable-name="true" :channel="channel" :checked="isChecked(channel)" />
<item-form v-if="isChecked(channel)" :item="newItem(channel)" :items="items" :createMode="true" :channel="channel" :checked="isChecked(channel)" />
</template>
<!-- <channel-link #default="{ channelId }" /> -->
</channel-group>

View File

@ -165,8 +165,8 @@ export default function itemDefaultListComponent (item, footer) {
}
if (!component.config.item) component.config.item = item.name
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.category && !component.config.icon) component.config.icon = item.category
if (item.category && component.config.iconUseState === undefined && !['Call', 'Image', 'Location'].includes(item.type)) component.config.iconUseState = true
if (item.label && footer && footer.contextLabelSource) {
let text = itemContextLabel(item, footer)
if (text) component.config.footer = text

View File

@ -2,21 +2,16 @@
<img v-if="iconType === 'oh'"
:src="iconUrl" v-bind="config" @click="performAction()"
:style="{
width: (context && config && config.width) ? config.width + 'px' : (width) ? width + 'px' : 'auto',
height: (context && config && config.height) ? config.height + 'px' : (height) ? height + 'px' : 'auto',
...(config) ? config.style : {} }"
width: (resolvedConfig.width !== null) ? resolvedConfig.width + 'px' : 'auto',
height: (resolvedConfig.height !== null) ? resolvedConfig.height + 'px' : 'auto',
...resolvedStyle }"
onload="this.classList.remove('no-icon')" onerror="this.classList.add('no-icon')">
<f7-icon v-else-if="iconType === 'f7'"
:ios="icon || ((config) ? config.icon : null)" :md="icon || ((config) ? config.icon : null)" :aurora="icon || ((config) ? config.icon : null)"
:color="color || ((config) ? config.color : null)" :size="width || height || ((config) ? (config.width || config.height) : null)"
:style="(config) ? config.style : null" />
<iconify-icon v-else-if="iconType === 'iconify'"
<f7-icon v-else-if="iconType === 'f7'" v-bind="resolvedConfig"
:size="resolvedConfig.width || resolvedConfig.height || null"
:style="resolvedStyle" />
<iconify-icon v-else-if="iconType === 'iconify'" v-bind="resolvedConfig"
:icon="iconName"
:width="width || ((config) ? config.width : null)" :height="height || ((config) ? config.height : null)"
:color="color || ((config) ? config.color : null)" :rotate="rotate || ((config) ? config.rotate : null)"
:horizontal-flip="horizontalFlip || ((config) ? config.horizontalFlip : null)"
:vertical-flip="verticalFlip || ((config) ? config.verticalFlip : null)"
:style="(config) ? config.style : null" />
:style="resolvedStyle" />
</template>
<style lang="stylus">
@ -35,7 +30,7 @@ export default {
components: {
'iconify-icon': Icon
},
props: ['icon', 'width', 'height', 'color', 'flip', 'state', 'rotate', 'horizontalFlip', 'verticalFlip'],
props: ['icon', 'width', 'height', 'color', 'state', 'rotate', 'horizontalFlip', 'verticalFlip'],
widget: OhIconDefinition,
data () {
return {
@ -45,6 +40,24 @@ export default {
}
},
computed: {
resolvedStyle () {
return {
...(this.config && this.config.style) ? this.config.style : {}
}
},
resolvedConfig () {
return {
width: (this.width) ? this.width : (this.config && this.config.width) ? this.config.width : null,
height: (this.height) ? this.height : (this.config && this.config.height) ? this.config.height : null,
color: (this.color) ? this.color : (this.config && this.config.color) ? this.config.color : null,
rotate: (this.rotate) ? this.rotate : (this.config && this.config.rotate) ? this.config.rotate : null,
horizontalFlip: (this.horizontalFlip) ? this.horizontalFlip : (this.config && this.config.horizontalFlip) ? this.config.horizontalFlip : null,
verticalFlip: (this.verticalFlip) ? this.verticalFlip : (this.config && this.config.verticalFlip) ? this.config.verticalFlip : null,
ios: (this.icon) ? this.icon : (this.config && this.config.icon) ? this.config.icon : null,
md: (this.icon) ? this.icon : (this.config && this.config.icon) ? this.config.icon : null,
aurora: (this.icon) ? this.icon : (this.config && this.config.icon) ? this.config.icon : null
}
},
iconType () {
const icon = (this.context) ? this.config.icon : this.icon
if (!icon) return 'oh'
@ -53,9 +66,20 @@ export default {
if (icon.indexOf('if') === 0 || icon.indexOf('iconify') === 0) return 'iconify'
return 'oh'
},
/**
* Icon set, for openHAB icons only.
* Defaults to 'classic'.
* @returns {*|string}
*/
iconSet () {
const icon = (this.context) ? this.config.icon : this.icon
if (icon.indexOf('oh:') === 0 && icon.split(':').length === 3) return icon.split(':')[1]
return 'classic'
},
iconName () {
const icon = (this.context) ? this.config.icon : this.icon
if (!(typeof icon === 'string' || icon instanceof String)) return ''
if (icon.indexOf('oh:') === 0 && icon.split(':').length === 3) return icon.split(':')[2]
if (icon.indexOf(':') >= 0) return icon.substring(icon.indexOf(':') + 1)
return icon
},
@ -90,7 +114,7 @@ export default {
methods: {
updateIcon () {
if (!this.currentIcon) return
this.$oh.media.getIcon(this.currentIcon, this.iconFormat, this.currentState).then((url) => {
this.$oh.media.getIcon(this.currentIcon, this.iconFormat, this.currentState, this.iconSet).then((url) => {
if (url !== this.iconUrl) {
this.iconUrl = url
}

View File

@ -2,10 +2,11 @@ import { getBasicCredentials } from '@/js/openhab/auth'
import Framework7 from 'framework7/framework7-lite.esm.bundle.js'
export default {
getIcon: (icon, format, state) => {
getIcon: (icon, format, state, iconSet) => {
if (!format) format = 'svg'
let url = `/icon/${icon}?format=${format}&anyFormat=true`
if (state) url += `&state=${encodeURIComponent(state)}`
if (iconSet) url += `&iconset=${iconSet}`
if (getBasicCredentials()) {
return new Promise((resolve, reject) => {

View File

@ -8,7 +8,7 @@
</f7-nav-right>
<f7-subnavbar sliding class="item-header">
<div class="item-icon" v-if="item.name">
<oh-icon v-if="item.category" :icon="item.category" height="60" width="60" />
<oh-icon v-if="item.category" :icon="item.category" :state="context.store[item.name] ? context.store[item.name].state : item.state" height="60" width="60" />
<span v-else>
{{ item.label ? item.label[0] : item.name[0] }}
</span>
@ -107,7 +107,7 @@
width 60px
padding 10px
border-radius 40px
background white
border 1px solid white
img
height 60px
width 60px

View File

@ -25,7 +25,7 @@
</div>
</f7-col>
<f7-col>
<item-form :item="item" :items="items" :enable-name="createMode" />
<item-form :item="item" :items="items" :createMode="createMode" />
</f7-col>
<f7-col>
<f7-block-title>Group Membership</f7-block-title>

View File

@ -1,5 +1,5 @@
<template>
<f7-page @page:beforein="load" @page:afterout="stopEventSource">
<f7-page @page:afterin="onPageAfterIn" @page:beforeout="onPageBeforeOut">
<f7-navbar title="Items" back-link="Settings" back-link-url="/settings/" back-link-force>
<f7-nav-right>
<f7-link icon-md="material:done_all" @click="toggleCheck()"
@ -52,7 +52,7 @@
</f7-col>
<f7-col v-show="ready">
<f7-block-title class="searchbar-hide-on-search">
{{ items.length }} items
{{ items.length }} Items
</f7-block-title>
<f7-list
v-show="items.length > 0"
@ -78,7 +78,8 @@
:subtitle="getItemTypeAndMetaLabel(item)"
:style="`top: ${vlData.topPosition}px`"
:after="(item.state) ? item.state : '\xa0'">
<oh-icon v-if="item.category" slot="media" :icon="item.category" height="32" width="32" />
<!-- Note: Using dynamic states is not possible since state tracking has a heavy performance impact -->
<oh-icon v-if="item.category" slot="media" :icon="item.category" :state="(item.state) ? item.state : null" height="32" width="32" />
<span v-else slot="media" class="item-initial">{{ item.name[0] }}</span>
<f7-icon v-if="!item.editable" slot="after-title" f7="lock_fill" size="1rem" color="gray" />
<!-- <f7-button slot="after-start" color="blue" icon-f7="compose" icon-size="24px" :link="`${item.name}/edit`"></f7-button> -->
@ -90,6 +91,9 @@
<f7-block v-if="ready && !items.length" class="service-config block-narrow">
<empty-state-placeholder icon="square_on_circle" title="items.title" text="items.text" />
</f7-block>
<f7-fab v-show="!showCheckboxes" position="center-bottom" text="Refresh" slot="fixed" color="blue" @click="load()">
<f7-icon ios="f7:arrow_clockwise" md="material:refresh" aurora="f7:arrow_clockwise" />
</f7-fab>
<f7-fab v-show="!showCheckboxes" position="right-bottom" slot="fixed" color="blue">
<f7-icon ios="f7:plus" md="material:add" aurora="f7:plus" />
<f7-icon ios="f7:multiply" md="material:close" aurora="f7:multiply" />
@ -139,6 +143,12 @@ export default {
}
},
methods: {
onPageAfterIn (event) {
this.load()
},
onPageBeforeOut (event) {
this.stopEventSource()
},
load () {
this.ready = false
this.$oh.api.get('/rest/items?metadata=semantics').then(data => {
@ -270,11 +280,6 @@ export default {
})
}
},
asyncComputed: {
iconUrl () {
return icon => this.$oh.media.getIcon(icon)
}
},
computed: {
searchPlaceholder () {
return window.innerWidth >= 1280 ? 'Search (for advanced search, use the developer sidebar (Shift+Alt+D))' : 'Search'

View File

@ -60,7 +60,7 @@
<div>Loading...</div>
</f7-block>
<div v-else-if="selectedThing.UID && selectedThingType.UID">
<item-form v-if="createEquipment" :item="newEquipmentItem" :items="items" :enable-name="true" :hide-type="true" :force-semantics="true" />
<item-form v-if="createEquipment" :item="newEquipmentItem" :items="items" :createMode="true" :hide-type="true" :force-semantics="true" />
<f7-block-title>Channels</f7-block-title>
<f7-block-footer class="padding-left padding-right">
Check the channels you wish to create as new Point items.

View File

@ -43,7 +43,7 @@
<!-- Create new item -->
<f7-col v-else>
<item-form :item="newItem" :items="items" :enable-name="true" @valid="itemValid = $event" />
<item-form :item="newItem" :items="items" :createMode="true" @valid="itemValid = $event" />
<f7-list>
<item-picker key="newItem-groups" title="Parent Group(s)" name="parent-groups" :value="newItem.groupNames" :items="items" @input="(value) => newItem.groupNames = value" :multiple="true" filterType="Group" />
</f7-list>

View File

@ -30,7 +30,7 @@
<span slot="media" class="item-initial">{{ (channel.label) ? channel.label[0] : (channelType.label) ? channelType.label[0] : '?' }}</span>
</f7-list-item>
<f7-list-item divider title="Item" />
<item :item="item" :context="context" :no-state="true" :link="'/settings/items/' + item.name" />
<item :item="item" :context="context" :link="'/settings/items/' + item.name" />
</ul>
</f7-list>
</f7-card-content>