Skip to content

Commit

Permalink
Merge 9f2281e into 0bcbd8c
Browse files Browse the repository at this point in the history
  • Loading branch information
hubsif authored Apr 16, 2021
2 parents 0bcbd8c + 9f2281e commit 70def48
Show file tree
Hide file tree
Showing 3 changed files with 128 additions and 65 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<f7-list-item :title="title" smart-select :smart-select-params="smartSelectParams" v-if="ready" ref="smartSelect" class="item-picker">
<select :name="name" :multiple="multiple" @change="select" :required="required">
<option value="" v-if="!multiple" />
<option v-for="item in items" :value="item.name" :key="item.name" :selected="(multiple) ? Array.isArray(value) && value.indexOf(item.name) >= 0 : value === item.name">
<option v-for="item in preparedItems" :value="item.name" :key="item.name" :selected="(multiple) ? Array.isArray(value) && value.indexOf(item.name) >= 0 : value === item.name">
{{ item.label ? item.label + ' (' + item.name + ')' : item.name }}
</option>
</select>
Expand All @@ -30,11 +30,11 @@
import ModelPickerPopup from '@/components/model/model-picker-popup.vue'
export default {
props: ['title', 'name', 'value', 'multiple', 'filterType', 'required', 'editableOnly'],
props: ['title', 'name', 'value', 'items', 'multiple', 'filterType', 'required', 'editableOnly'],
data () {
return {
ready: false,
items: [],
preparedItems: [],
icons: {},
smartSelectParams: {
view: this.$f7.view.main,
Expand All @@ -48,23 +48,30 @@ export default {
},
created () {
this.smartSelectParams.closeOnSelect = !(this.multiple)
// TODO use a Vuex store
this.$oh.api.get('/rest/items').then((data) => {
this.items = data.sort((a, b) => {
if (!this.items) {
// TODO use a Vuex store
this.$oh.api.get('/rest/items').then((items) => {
this.sortAndFilterItems(items)
})
} else {
this.sortAndFilterItems(this.items)
}
},
methods: {
sortAndFilterItems (items) {
this.preparedItems = items.sort((a, b) => {
const labelA = a.label || a.name
const labelB = b.label || b.name
return labelA.localeCompare(labelB)
})
if (this.filterType) {
this.items = this.items.filter((i) => i.type === this.filterType)
this.preparedItems = this.preparedItems.filter((i) => i.type === this.filterType)
}
if (this.editableOnly) {
this.items = this.items.filter((i) => i.editable)
this.preparedItems = this.preparedItems.filter((i) => i.editable)
}
this.ready = true
})
},
methods: {
},
select (e) {
this.$f7.input.validateInputs(this.$refs.smartSelect.$el)
const value = this.$refs.smartSelect.f7SmartSelect.getValue()
Expand Down
100 changes: 69 additions & 31 deletions bundles/org.openhab.ui/web/src/components/item/item-form.vue
Original file line number Diff line number Diff line change
@@ -1,34 +1,39 @@
<template>
<div v-if="item" class="quick-link-form no-padding">
<f7-list inline-labels no-hairlines-md>
<f7-list-input v-if="!enableName" label="Name" type="text" placeholder="Name" :value="item.name" disabled />
<f7-list-input v-else label="Name" type="text" placeholder="Name" :value="item.name"
@input="item.name = $event.target.value" clear-button
required validate pattern="[A-Za-z0-9_]+" error-message="Required. Alphanumeric &amp; underscores only" />
<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}">
<select name="select-type" @change="item.type = $event.target.value">
<optgroup label="Basic Types">
<option v-for="type in types.ItemTypes" :key="type" :value="type" :selected="type === item.type">
{{ type }}
</option>
</optgroup>
<optgroup label="Numbers with Dimensions">
<option v-for="dimension in types.Dimensions" :key="dimension" :value="'Number:' + dimension" :selected="item.type === 'Number:' + dimension">
{{ 'Number:' + dimension }}
</option>
</optgroup>
</select>
</f7-list-item>
<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" />
</div>
</f7-list-input>
</f7-list>
<semantics-picker v-if="!hideSemantics" :item="item" :same-class-only="true" :hide-type="true" :hide-none="forceSemantics" />
<div v-if="!ready" class="text-align-center">
<f7-preloader />
<div>Loading...</div>
</div>
<template v-else>
<f7-list inline-labels no-hairlines-md>
<f7-list-input v-if="!enableName" label="Name" type="text" placeholder="Name" :value="item.name" disabled />
<f7-list-input v-else label="Name" type="text" placeholder="Name" :value="item.name"
@input="onNameInput" clear-button required :error-message="nameErrorMessage" :error-message-force="!!nameErrorMessage" />
<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}">
<select name="select-type" @change="item.type = $event.target.value">
<optgroup label="Basic Types">
<option v-for="type in types.ItemTypes" :key="type" :value="type" :selected="type === item.type">
{{ type }}
</option>
</optgroup>
<optgroup label="Numbers with Dimensions">
<option v-for="dimension in types.Dimensions" :key="dimension" :value="'Number:' + dimension" :selected="item.type === 'Number:' + dimension">
{{ 'Number:' + dimension }}
</option>
</optgroup>
</select>
</f7-list-item>
<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" />
</div>
</f7-list-input>
</f7-list>
<semantics-picker v-if="!hideSemantics" :item="item" :same-class-only="true" :hide-type="true" :hide-none="forceSemantics" />
</template>
</div>
</template>

Expand All @@ -46,15 +51,18 @@ import * as Types from '@/assets/item-types.js'
import { Categories } from '@/assets/categories.js'
export default {
props: ['item', 'enableName', 'hideCategory', 'hideType', 'hideSemantics', 'forceSemantics'],
props: ['item', 'items', 'enableName', 'hideCategory', 'hideType', 'hideSemantics', 'forceSemantics'],
components: {
SemanticsPicker
},
data () {
return {
ready: !this.enableName,
types: Types,
categoryInputId: '',
categoryAutocomplete: null
categoryAutocomplete: null,
allItems: [],
nameErrorMessage: ''
}
},
methods: {
Expand All @@ -70,6 +78,36 @@ export default {
}
}
})
},
onNameInput (event) {
this.item.name = event.target.value
this.validateName(this.item.name)
},
validateName (name) {
let oldError = this.nameErrorMessage
if (!/^[A-Za-z0-9_]+$/.test(name)) {
this.nameErrorMessage = 'Required. Alphanumeric & underscores only'
} else if (this.allItems.some(item => item.name === name)) {
this.nameErrorMessage = 'An item with this name already exists'
} else {
this.nameErrorMessage = ''
}
if (oldError !== this.nameErrorMessage) this.$emit('valid', !this.nameErrorMessage)
}
},
created () {
if (this.enableName) {
if (!this.items) {
this.$oh.api.get('/rest/items').then((items) => {
this.allItems = items
this.validateName(this.item.name)
this.ready = true
})
} else {
this.allItems = this.items
this.validateName(this.item.name)
this.ready = true
}
}
},
mounted () {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,31 +19,36 @@
</f7-list>
</f7-col>

<!-- Option to create new item (if not supplied by prop) -->
<f7-col v-if="!item">
<f7-block-title>Item</f7-block-title>
<f7-list media-list>
<f7-list-item radio :checked="createItem === false" value="false" @change="createItem = false" title="Use an existing Item" name="item-creation-choice" />
<f7-list-item radio :checked="createItem === true" value="true" @change="createItem = true" title="Create a new Item" name="item-creation-choice" />
</f7-list>
</f7-col>
<div v-if="!item && !items" class="text-align-center">
<f7-preloader />
<div>Loading...</div>
</div>
<template v-if="!item && items">
<!-- Option to create new item (if not supplied by prop) -->
<f7-col>
<f7-block-title>Item</f7-block-title>
<f7-list media-list>
<f7-list-item radio :checked="!createItem" value="false" @change="createItem = false" title="Use an existing Item" name="item-creation-choice" />
<f7-list-item radio :checked="createItem" value="true" @change="createItem = true" title="Create a new Item" name="item-creation-choice" />
</f7-list>
</f7-col>

<!-- Choose item to link -->
<f7-col v-if="createItem === false && !item">
<f7-list>
<!-- TODO: filter with compatible item types -->
<item-picker key="itemLink" title="Item to Link" name="item" :value="selectedItemName" :multiple="false"
@input="(value) => selectedItemName = value" />
</f7-list>
</f7-col>
<!-- 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" />
</f7-list>
</f7-col>

<!-- Create new item -->
<f7-col v-else-if="createItem === true">
<item-form :item="newItem" :enable-name="true" />
<f7-list>
<item-picker key="newItem-groups" title="Parent Group(s)" name="parent-groups" :value="newItem.groupNames" @input="(value) => newItem.groupNames = value" :multiple="true" filterType="Group" />
</f7-list>
</f7-col>
<!-- Create new item -->
<f7-col v-else>
<item-form :item="newItem" :enable-name="true" :items="items" @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>
</f7-col>
</template>

<!-- Item to link supplied as prop -->
<f7-col v-else-if="item">
Expand Down Expand Up @@ -138,6 +143,8 @@ export default {
return {
ready: true,
createItem: false,
items: false,
itemValid: true,
link: {
itemName: null,
channelUID: null,
Expand All @@ -159,6 +166,13 @@ export default {
semanticClasses: SemanticClasses
}
},
created () {
if (!this.item) {
this.$oh.api.get('/rest/items').then((items) => {
this.items = items
})
}
},
methods: {
onPageAfterIn (event) {
if (!this.channel) return
Expand Down Expand Up @@ -247,6 +261,10 @@ export default {
}
// checks
if (this.createItem && !this.itemValid) {
this.$f7.dialog.alert('Please correct the item to link')
return
}
if (!link.itemName) {
this.$f7.dialog.alert('Please configure the item to link')
return
Expand Down

0 comments on commit 70def48

Please sign in to comment.