Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Items: Show non-semantic tags, relatesTo part of semantics & Use accordion tag input & Fix virtual box height #2087

Merged
merged 9 commits into from
Sep 26, 2023
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
</f7-block-title>
<f7-list>
<ul>
<item v-for="item in pinnedObjects.items" :key="item.name" link="" :item="item" :context="context" :no-icon="true" :no-type="true" @click="(evt) => showItem(evt, item)">
<item v-for="item in pinnedObjects.items" :key="item.name" link="" :item="item" :context="context" :no-icon="true" :no-type="true" :no-tags="true" @click="(evt) => showItem(evt, item)">
<div class="display-flex align-items-flex-end justify-content-flex-end" style="margin-top: 3px" slot="footer">
<f7-link class="margin-right itemlist-actions" color="gray" icon-f7="pencil" icon-size="18" tooltip="Edit" :href="'/settings/items/' + item.name" :animate="false" />
<f7-link class="itemlist-actions" color="red" icon-f7="pin_slash_fill" icon-size="18" tooltip="Unpin" @click="unpin('items', item, 'name')" />
Expand Down
19 changes: 18 additions & 1 deletion bundles/org.openhab.ui/web/src/components/item/item-form.vue
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@
</f7-list-input>
</f7-list>
<semantics-picker v-if="!hideSemantics" :item="item" :same-class-only="true" :hide-type="true" :hide-none="forceSemantics" />
<f7-list inline-labels accordion-list no-hairline-md>
<f7-list-item accordion-item title="Non-Semantic Tags" :after="numberOfTags">
<f7-accordion-content>
<tag-input :item="item" />
</f7-accordion-content>
</f7-list-item>
</f7-list>
</div>
</template>

Expand All @@ -42,13 +49,18 @@

<script>
import SemanticsPicker from '@/components/tags/semantics-picker.vue'
import TagInput from '@/components/tags/tag-input.vue'
import * as Types from '@/assets/item-types.js'
import { Categories } from '@/assets/categories.js'

import ItemMixin from '@/components/item/item-mixin'

export default {
mixins: [ItemMixin],
props: ['item', 'items', 'createMode', 'hideCategory', 'hideType', 'hideSemantics', 'forceSemantics'],
components: {
SemanticsPicker
SemanticsPicker,
TagInput
},
data () {
return {
Expand All @@ -58,6 +70,11 @@ export default {
nameErrorMessage: ''
}
},
computed: {
numberOfTags () {
return this.getNonSemanticTags(this.item).length
}
},
methods: {
initializeAutocomplete (inputElement) {
this.categoryAutocomplete = this.$f7.autocomplete.create({
Expand Down
29 changes: 29 additions & 0 deletions bundles/org.openhab.ui/web/src/components/item/item-mixin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import TagMixin from '@/components/tags/tag-mixin'

export default {
mixins: [TagMixin],
methods: {
getItemTypeAndMetaLabel (item) {
let ret = item.type
if (item.metadata && item.metadata.semantics) {
ret += ' · '
const classParts = item.metadata.semantics.value.split('_')
ret += classParts[0]
if (classParts.length > 1) {
ret += ' > ' + classParts.pop()
if (item.metadata.semantics.config && item.metadata.semantics.config.relatesTo) {
const relatesToParts = item.metadata.semantics.config.relatesTo.split('_')
if (relatesToParts.length > 1) {
ret += ' > ' + relatesToParts.pop()
}
}
}
}
return ret
},
getNonSemanticTags (item) {
if (!item.tags) return []
return item.tags.filter((t) => !this.isSemanticTag(t))
}
}
}
28 changes: 10 additions & 18 deletions bundles/org.openhab.ui/web/src/components/item/item.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,40 +5,32 @@
:link="link"
:title="(item.label) ? item.label :item.name"
:footer="(item.label) ? item.name : '\xa0'"
:subtitle="getItemTypeAndMetaLabel(item)"
:subtitle="noType ? '' : getItemTypeAndMetaLabel(item)"
:after="state"
v-on="$listeners">
<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 />
<div v-if="!noTags" slot="subtitle">
<f7-chip v-for="tag in getNonSemanticTags(item)" :key="tag" :text="tag" media-bg-color="blue" style="margin-right: 6px">
<f7-icon slot="media" ios="f7:tag_fill" md="material:label" aurora="f7:tag_fill" />
</f7-chip>
</div>
</f7-list-item>
</template>

<script>
import ItemMixin from '@/components/item/item-mixin'

export default {
props: ['item', 'context', 'ignoreEditable', 'noState', 'noType', 'noIcon', 'link'],
mixins: [ItemMixin],
props: ['item', 'context', 'ignoreEditable', 'noState', 'noType', 'noIcon', 'noTags', 'link'],
computed: {
state () {
if (this.noState) return
if (!this.context || !this.context.store) return this.item.state
return this.context.store[this.item.name].displayState || this.context.store[this.item.name].state
}
},
methods: {
getItemTypeAndMetaLabel () {
if (this.noType) return
let ret = this.item.type
if (this.item.metadata && this.item.metadata.semantics) {
ret += ' · '
const classParts = this.item.metadata.semantics.value.split('_')
ret += classParts[0]
if (classParts.length > 1) {
ret += '>' + classParts.pop()
}
}
return ret
}
}
}
</script>
12 changes: 4 additions & 8 deletions bundles/org.openhab.ui/web/src/components/tags/tag-input.vue
Original file line number Diff line number Diff line change
Expand Up @@ -25,21 +25,17 @@
</template>

<script>
import TagMixin from '@/components/tags/tag-mixin'

export default {
mixins: [TagMixin],
props: ['item', 'disabled', 'inScriptEditor'],
data () {
return {
pendingTag: '',
semanticClasses: this.$store.getters.semanticClasses
pendingTag: ''
}
},
methods: {
isSemanticTag (tag) {
return [this.semanticClasses.Locations,
this.semanticClasses.Equipment,
this.semanticClasses.Points,
this.semanticClasses.Properties].some((t) => t.indexOf(tag) >= 0)
},
isScriptTag (tag) {
if (this.inScriptEditor !== true) return false
if (tag === 'Script') return true
Expand Down
15 changes: 15 additions & 0 deletions bundles/org.openhab.ui/web/src/components/tags/tag-mixin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
export default {
data () {
return {
semanticClasses: this.$store.getters.semanticClasses
}
},
methods: {
isSemanticTag (tag) {
return [this.semanticClasses.Locations,
this.semanticClasses.Equipment,
this.semanticClasses.Points,
this.semanticClasses.Properties].some((t) => t.indexOf(tag) >= 0)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,10 @@ import AddLinkPage from '@/pages/settings/things/link/link-add.vue'
import ConfigureLinkPage from '@/pages/settings/things/link/link-edit.vue'
import ConfigureChannelPage from '@/pages/settings/things/channel/channel-edit.vue'

import ItemMixin from '@/components/item/item-mixin'

export default {
mixins: [ItemMixin],
props: ['channelType', 'channelId', 'channel', 'thing', 'opened', 'extensible', 'context'],
data () {
return {
Expand Down Expand Up @@ -203,18 +206,6 @@ export default {
self.thing.channels.splice(idx, 1)
self.$emit('channel-updated', true)
})
},
getItemTypeAndMetaLabel (item) {
let ret = item.type
if (item.metadata && item.metadata.semantics) {
ret += ' · '
const classParts = item.metadata.semantics.value.split('_')
ret += classParts[0]
if (classParts.length > 1) {
ret += '>' + classParts.pop()
}
}
return ret
}
},
watch: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,6 @@
<f7-block-title>Group Settings</f7-block-title>
<group-form :item="item" />
</f7-col>
<f7-col class="tags-editor">
<f7-block-title>Non-Semantic Tags</f7-block-title>
<tag-input :item="item" />
</f7-col>
</f7-block>
</f7-tab>

Expand Down Expand Up @@ -79,7 +75,6 @@ import YAML from 'yaml'

import ItemForm from '@/components/item/item-form.vue'
import GroupForm from '@/components/item/group-form.vue'
import TagInput from '@/components/tags/tag-input.vue'
import ItemPicker from '@/components/config/controls/item-picker.vue'
import DirtyMixin from '../dirty-mixin'

Expand All @@ -90,7 +85,6 @@ export default {
ItemPicker,
ItemForm,
GroupForm,
TagInput,
'editor': () => import(/* webpackChunkName: "script-editor" */ '@/components/config/controls/script-editor.vue')
},
data () {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
ref="itemsList"
media-list
virtual-list
:virtual-list-params="{ items, searchAll, renderExternal, height: vlData.height }">
:virtual-list-params="{ items, searchAll, renderExternal, height }">
<ul>
<f7-list-item
v-for="(item, index) in vlData.items"
Expand All @@ -86,6 +86,11 @@
<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> -->
<div slot="subtitle">
<f7-chip v-for="tag in getNonSemanticTags(item)" :key="tag" :text="tag" media-bg-color="blue" style="margin-right: 6px">
<f7-icon slot="media" ios="f7:tag_fill" md="material:label" aurora="f7:tag_fill" />
</f7-chip>
</div>
</f7-list-item>
</ul>
</f7-list>
Expand Down Expand Up @@ -127,23 +132,20 @@
</style>

<script>
import ItemMixin from '@/components/item/item-mixin'

export default {
mixins: [ItemMixin],
components: {
'empty-state-placeholder': () => import('@/components/empty-state-placeholder.vue')
},
data () {
let vlHeight
if (this.$theme.ios) vlHeight = 78
if (this.$theme.aurora) vlHeight = 60
if (this.$theme.md) vlHeight = 87
if (this.$device.firefox) vlHeight += 1
return {
ready: false,
items: [], // [{ label: 'Staircase', name: 'Staircase'}],
indexedItems: {},
vlData: {
items: [],
height: vlHeight
items: []
},
selectedItems: [],
showCheckboxes: false,
Expand Down Expand Up @@ -203,6 +205,7 @@ export default {
for (let i = 0; i < items.length; i += 1) {
let haystack = items[i].name
if (items[i].label) haystack += ' ' + items[i].label
if (items[i].tags) for (let j = 0; j < items[i].tags.length; j += 1) haystack += ' ' + items[i].tags[j]
haystack += ' ' + this.getItemTypeAndMetaLabel(items[i])
if (
haystack.toLowerCase().indexOf(query.toLowerCase()) >= 0 ||
Expand All @@ -214,17 +217,29 @@ export default {
renderExternal (vl, vlData) {
this.vlData = vlData
},
getItemTypeAndMetaLabel (item) {
let ret = item.type
if (item.metadata && item.metadata.semantics) {
ret += ' · '
const classParts = item.metadata.semantics.value.split('_')
ret += classParts[0]
if (classParts.length > 1) {
ret += '>' + classParts.pop()
height (item) {
let vlHeight
if (this.$theme.ios) vlHeight = 78
if (this.$theme.aurora) vlHeight = 60.77
if (this.$theme.md) vlHeight = 87.4
if (this.$device.macos) {
if (window.navigator.userAgent.includes('Safari') && !window.navigator.userAgent.includes('Chrome')) vlHeight -= 0.77
}
if (item.tags) {
let tagsNonS = item.tags
if (item.metadata && item.metadata.semantics) {
tagsNonS = item.tags.filter((t) =>
t !== item.metadata.semantics.value.split('_').pop() &&
t !== ((item.metadata.semantics.config && item.metadata.semantics.config.relatesTo) ? item.metadata.semantics.config.relatesTo.split('_').pop() : '')
)
}
if (tagsNonS.length) {
vlHeight += 24
if (this.$theme.ios) vlHeight += 4
if (this.$theme.md) vlHeight += 12
}
}
return ret
return vlHeight
},
toggleCheck () {
this.showCheckboxes = !this.showCheckboxes
Expand Down