Link and Profile related fixes (#1043)

Drop "no profile" and use the "Default" profile instead (link-add and link-edit)
Filter the item list for items compatible to the channel's type (link-add)
Only allow profiles compatible to the current item
(disable on link-add, filter on link-edit)
Add profile config sheet key to prevent VNodes reuse.

Fix #884.
Fix #885.

Signed-off-by: Hubert Nusser <hubsif@gmx.de>
Also-by: Yannick Schaus <github@schaus.net>
pull/1052/head
hubsif 2021-05-16 20:18:54 +02:00 committed by GitHub
parent 65df3b3191
commit f590b28331
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 61 additions and 47 deletions

View File

@ -65,7 +65,11 @@ export default {
return labelA.localeCompare(labelB)
})
if (this.filterType) {
this.preparedItems = this.preparedItems.filter((i) => i.type === this.filterType)
if (Array.isArray(this.filterType)) {
this.preparedItems = this.preparedItems.filter((i) => this.filterType.includes(i.type.split(':', 1)[0]))
} else {
this.preparedItems = this.preparedItems.filter((i) => i.type === this.filterType)
}
}
if (this.editableOnly) {
this.preparedItems = this.preparedItems.filter((i) => i.editable)

View File

@ -15,7 +15,7 @@
<f7-list-item media-item class="channel-item"
:title="channel.label || channelType.label"
:footer="channel.description || channelType.description"
:subtitle="channel.uid" />
:subtitle="channel.uid + ' (' + getItemType(channel) + ')'" />
</f7-list>
</f7-col>
@ -36,8 +36,8 @@
<!-- Choose item to link -->
<f7-col v-if="!createItem">
<f7-list>
<!-- TODO: filter with compatible item types -->
<item-picker key="itemLink" title="Item to Link" name="item" :value="selectedItemName" :multiple="false" :items="items" @input="(value) => selectedItemName = value" />
<item-picker key="itemLink" title="Item to Link" name="item" :value="selectedItemName" :multiple="false" :items="items" :filterType="getCompatibleItemTypes()"
@input="(value) => selectedItemName = value" />
</f7-list>
</f7-col>
@ -70,17 +70,13 @@
</div>
</f7-col>
<!-- <f7-block v-if="!itemTypeCompatible()" class="text-color-red">
The channel and the item type are not compatible.
</f7-block> -->
<f7-block v-if="!ready && !(!item && !items)" class="text-align-center">
<f7-preloader />
<div>Loading...</div>
</f7-block>
<!-- Profile configuration -->
<f7-col v-else-if="profileTypes.length">
<f7-col v-else-if="profileTypes.length && currentItem">
<f7-block-title>Profile</f7-block-title>
<f7-block-footer class="padding-left padding-right">
Profiles define how Channels and Items work together. Install transformation add-ons to get additional profiles.
@ -88,10 +84,11 @@
Learn more about profiles.
</f7-link>
</f7-block-footer>
<f7-list>
<f7-list-item radio :checked="!currentProfileType" value="" @change="onProfileTypeChange()" title="(No Profile)" name="profile-type" />
<f7-list-item radio v-for="profileType in profileTypes"
:value="profileType.uid"
<f7-list class="profile-list profile-disabled">
<f7-list-item radio v-for="profileType in profileTypes" class="profile-item"
:checked="!currentProfileType && profileType.uid === 'system:default' || currentProfileType && profileType.uid === currentProfileType.uid"
:disabled="!compatibleProfileTypes.includes(profileType)"
:class="{ 'profile-disabled': !compatibleProfileTypes.includes(profileType) }"
@change="onProfileTypeChange(profileType.uid)"
:key="profileType.uid" :title="profileType.label" name="profile-type" />
</f7-list>
@ -99,6 +96,7 @@
<f7-col v-if="profileTypeConfiguration != null">
<f7-block-title>Profile Configuration</f7-block-title>
<config-sheet ref="profileConfiguration"
:key="'profileTypeConfiguration-' + currentProfileType.uid"
:parameter-groups="profileTypeConfiguration.parameterGroups"
:parameters="profileTypeConfiguration.parameters"
:configuration="configuration" />
@ -115,6 +113,16 @@
</f7-page>
</template>
<style lang="stylus">
.profile-list
.profile-item.profile-disabled
pointer-events none
.icon-radio
opacity 0.3
.item-title
opacity 0.55
</style>
<script>
import diacritic from 'diacritic'
@ -173,6 +181,15 @@ export default {
})
}
},
computed: {
currentItem () {
return this.item ? this.item : this.createItem ? this.newItem : this.selectedItemName
},
compatibleProfileTypes () {
let currentItemType = this.currentItem ? this.currentItem.type : null
return this.profileTypes.filter(p => !p.supportedItemTypes.length || p.supportedItemTypes.includes(currentItemType))
}
},
methods: {
onPageAfterIn (event) {
if (!this.channel) return
@ -195,6 +212,7 @@ export default {
const getProfileTypes = this.$oh.api.get('/rest/profile-types?channelTypeUID=' + channel.channelTypeUID)
getProfileTypes.then((data) => {
this.profileTypes = data
this.profileTypes.unshift(data.splice(data.findIndex(p => p.uid === 'system:default'), 1)[0]) // move default to be first
this.ready = true
})
},
@ -214,30 +232,16 @@ export default {
this.profileTypeConfiguration = null
})
},
itemTypeCompatible () {
// debugger
// TODO move to testable .js file
let item = this.item
if (!item) item = (this.createItem) ? this.newItem : this.selectedItem
if (!item) return true
if (!item.type) return true
if (!this.selectedChannel) return true
if (!this.selectedChannel.itemType) return false
if (this.currentProfileType && this.currentProfileType.supportedItemTypes && this.currentProfileType.supportedItemTypes.length > 0) {
return (this.currentProfileType.supportedItemTypes.indexOf(this.item.type) >= 0)
}
const channelItemType = this.selectedChannel.itemType
if (channelItemType === item.type) return true
// Exceptions
if (item.type.indexOf('Number') === 0 && channelItemType.indexOf('Number') === 0) return true
if (item.type.indexOf('Number') === 0 && channelItemType === 'Dimmer') return true
if (channelItemType === 'Color' && (item.type === 'Dimmer' || item.type === 'Switch')) return true
if (channelItemType === 'Dimmer' && item.type === 'Switch') return true
return false
getItemType (channel) {
if (channel && channel.kind === 'TRIGGER') return 'Trigger'
if (!channel || !channel.itemType) return '?'
return channel.itemType
},
getCompatibleItemTypes () {
let compatibleItemTypes = this.channel.itemType.split(':', 1)
if (this.channel.itemType === 'Color') { compatibleItemTypes.push('Switch', 'Dimmer') }
if (this.channel.itemType === 'Dimmer') { compatibleItemTypes.push('Switch') }
return compatibleItemTypes
},
save () {
const link = {}
@ -277,11 +281,6 @@ export default {
this.$f7.dialog.alert('Please review the profile configuration and correct validation errors')
return
}
// temporarily disabled
// if (!this.itemTypeCompatible()) {
// this.$f7.dialog.alert('The channel and item type are not compatible')
// return
// }
if (this.createItem) {
this.$oh.api.put('/rest/items/' + this.newItem.name, this.newItem).then((data) => {
@ -327,6 +326,11 @@ export default {
this.ready = true
})
})
},
currentItem () {
if (this.currentProfileType && !this.compatibleProfileTypes.find(p => p.uid === this.currentProfileType.uid)) {
this.currentProfileType = null
}
}
}
}

View File

@ -23,7 +23,7 @@
<f7-list-item divider title="Channel" />
<f7-list-item media-item class="channel-item"
:title="channel.label || channelType.label"
:footer="channel.uid"
:footer="channel.uid + ' (' + getItemType(channel) + ')'"
:subtitle="thing.label"
:badge="thingStatusBadgeText(thing.statusInfo)"
:badge-color="thingStatusBadgeColor(thing.statusInfo)">
@ -56,9 +56,8 @@
<div>Loading...</div>
</f7-block>
<f7-list v-else>
<f7-list-item radio :checked="!currentProfileType" value="" @change="onProfileTypeChange()" title="(No Profile)" name="profile-type" :disabled="!link.editable" />
<f7-list-item radio v-for="profileType in profileTypes"
:checked="currentProfileType && profileType.uid === currentProfileType.uid"
:checked="!currentProfileType && profileType.uid === 'system:default' || currentProfileType && profileType.uid === currentProfileType.uid"
:disabled="!link.editable"
@change="onProfileTypeChange(profileType.uid)"
:key="profileType.uid" :title="profileType.label" name="profile-type" />
@ -68,6 +67,7 @@
<f7-col v-if="profileTypeConfiguration != null">
<f7-block-title>Profile Configuration</f7-block-title>
<config-sheet ref="profileConfiguration"
:key="'profileTypeConfiguration-' + currentProfileType.uid"
:parameter-groups="profileTypeConfiguration.parameterGroups"
:parameters="profileTypeConfiguration.parameters"
:configuration="link.configuration"
@ -123,9 +123,10 @@ export default {
const itemName = this.item.name
const itemType = this.item.type
const channelUID = this.channel.uid.replace('#', '%23')
const getProfileTypes = this.$oh.api.get('/rest/profile-types?channelTypeUID=' + this.channel.channelTypeUID + '&itemType=' + itemType)
getProfileTypes.then((data) => {
this.$oh.api.get('/rest/profile-types?channelTypeUID=' + this.channel.channelTypeUID + '&itemType=' + itemType).then((data) => {
this.profileTypes = data
this.profileTypes.unshift(data.splice(data.findIndex(p => p.uid === 'system:default'), 1)[0]) // move default to be first
this.profileTypes = this.profileTypes.filter(p => !p.supportedItemTypes.length || p.supportedItemTypes.includes(this.item.type)) // only show compatible profile types
this.$oh.api.get('/rest/links/' + itemName + '/' + channelUID).then((data2) => {
this.link = data2
@ -155,6 +156,11 @@ export default {
this.profileTypeConfiguration = null
})
},
getItemType (channel) {
if (channel && channel.kind === 'TRIGGER') return 'Trigger'
if (!channel || !channel.itemType) return '?'
return channel.itemType
},
unlink () {
this.$f7.dialog.confirm(
`Are you sure you want to unlink ${this.item.name} from ${this.thing.label}?`,