Add Items from Thing: Expert Mode (#603)
This adds a new "expert mode" to the "Create Equipment from Thing"/"Add Equipment to Model"/ "Create Points from Thing"/"Add Points to Model" Instead of clicking through the channels and filling out items, a textual definition will be generated and put it the "Add Items from Textual Definition" page. That way, the expert user can add their items by editing text with the well-known syntax. Signed-off-by: Yannick Schaus <github@schaus.net>pull/606/merge
parent
e26eac6656
commit
6f81c0a6c6
|
@ -93,7 +93,7 @@ import ChannelGroup from './channel-group.vue'
|
|||
import ChannelLink from './channel-link.vue'
|
||||
import ItemForm from '@/components/item/item-form.vue'
|
||||
|
||||
import Points from '@/assets/semantics'
|
||||
import { Points } from '@/assets/semantics'
|
||||
|
||||
export default {
|
||||
props: ['thingType', 'thing', 'channelTypes', 'pickerMode', 'multipleLinksMode', 'itemTypeFilter', 'newItemsPrefix', 'newItems', 'context'],
|
||||
|
|
|
@ -112,9 +112,10 @@ export default {
|
|||
components: {
|
||||
'editor': () => import('@/components/config/controls/script-editor.vue')
|
||||
},
|
||||
props: ['textualDefinition'],
|
||||
data () {
|
||||
return {
|
||||
itemsDsl: '',
|
||||
itemsDsl: this.textualDefinition || '',
|
||||
items: [],
|
||||
things: [],
|
||||
links: [],
|
||||
|
|
|
@ -62,6 +62,7 @@
|
|||
You can alter the suggested names and labels as well as the semantic class and related property.<br/><br/>
|
||||
The newly created Points will be linked to their respective channels with the default profile
|
||||
(you will be able to configure the links individually later if needed).
|
||||
<f7-link class="display-block margin-top-half" @click="switchToExpertMode" color="blue">Expert Mode</f7-link>
|
||||
</f7-block-footer>
|
||||
<channel-list :thing="selectedThing" :thingType="selectedThingType" :channelTypes="selectedThingChannelTypes"
|
||||
:multiple-links-mode="true" :new-items-prefix="(createEquipment) ? newEquipmentItem.name : (parentGroup) ? parentGroup.name : ''"
|
||||
|
@ -91,6 +92,8 @@ import Item from '@/components/item/item.vue'
|
|||
|
||||
import ThingStatus from '@/components/thing/thing-status-mixin'
|
||||
|
||||
import generateTextualDefinition from './generate-textual-definition'
|
||||
|
||||
export default {
|
||||
mixins: [ThingStatus],
|
||||
components: {
|
||||
|
@ -120,8 +123,30 @@ export default {
|
|||
this.selectedThingId = this.thingId
|
||||
}
|
||||
},
|
||||
toggleSelect (channel) {
|
||||
switchToExpertMode () {
|
||||
try {
|
||||
let parentGroupsForEquipment, parentGroupsForPoints
|
||||
if (this.createEquipment) {
|
||||
parentGroupsForEquipment = (this.parentGroup) ? [this.parentGroup.name] : []
|
||||
parentGroupsForPoints = [this.newEquipmentItem.name]
|
||||
} else {
|
||||
parentGroupsForEquipment = []
|
||||
parentGroupsForPoints = (this.parent) ? [this.parent.item.name] : (this.parentGroup) ? [this.parentGroup.name] : []
|
||||
}
|
||||
|
||||
const itemsDefinition = generateTextualDefinition(this.selectedThing, this.selectedThingChannelTypes, (this.createEquipment) ? this.newEquipmentItem : null, parentGroupsForEquipment, parentGroupsForPoints)
|
||||
|
||||
this.$f7router.navigate('/settings/items/add-from-textual-definition', {
|
||||
props: {
|
||||
textualDefinition: itemsDefinition
|
||||
},
|
||||
pushState: false,
|
||||
reloadCurrent: true
|
||||
})
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
this.$f7.dialog.alert('There was an error generating the items definition: ' + e)
|
||||
}
|
||||
},
|
||||
add () {
|
||||
if (!this.selectedThingId) {
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
import diacritic from 'diacritic'
|
||||
import { Points } from '@/assets/semantics'
|
||||
|
||||
/**
|
||||
* Generate a textual definition for the items provided by the "add from thing" page,
|
||||
* for expert users who prefer to edit their items that way
|
||||
*/
|
||||
export default (thing, channelTypes, newEquipmentItem, parentGroupsForEquipment, parentGroupsForPoints) => {
|
||||
const channelTypesMap = new Map(channelTypes.map(ct => [ct.UID, ct]))
|
||||
|
||||
let def = ''
|
||||
if (newEquipmentItem && newEquipmentItem.name) {
|
||||
def += `// Equipment representing thing:\n// ${thing.UID}\n`
|
||||
def += `// (${thing.label})\n\n`
|
||||
|
||||
def += `Group ${newEquipmentItem.name} "${newEquipmentItem.label}" `
|
||||
if (newEquipmentItem.category) def += `<${newEquipmentItem.category}> `
|
||||
if (parentGroupsForEquipment.length) def += `(${parentGroupsForEquipment.join(', ')}) `
|
||||
if (newEquipmentItem.tags.length) def += `[${newEquipmentItem.tags.map((t) => `"${t}"`).join(', ')}] `
|
||||
def = def.trim() + '\n\n'
|
||||
}
|
||||
|
||||
let lines = []
|
||||
for (const channel of thing.channels) {
|
||||
if (channel.kind !== 'STATE') continue
|
||||
const channelType = channelTypesMap.get(channel.channelTypeUID)
|
||||
let newItemName = (newEquipmentItem) ? newEquipmentItem.name : diacritic.clean(thing.label).replace(/[^0-9a-z]/gi, '')
|
||||
newItemName += '_'
|
||||
let suffix = channel.label || channel.id
|
||||
if (thing.channels.filter((c) => c.label === suffix).length > 1) {
|
||||
suffix = channel.id.replace('#', '_')
|
||||
}
|
||||
newItemName += diacritic.clean(suffix).replace(/[^0-9a-z_]/gi, '')
|
||||
const defaultTags = (channel.defaultTags.length > 0) ? channel.defaultTags : channelType.tags
|
||||
const newItem = {
|
||||
channel: channel,
|
||||
channelType: channelType,
|
||||
name: newItemName,
|
||||
label: channel.label || channelType.label,
|
||||
groupNames: parentGroupsForPoints,
|
||||
category: (channelType) ? channelType.category : '',
|
||||
type: channel.itemType,
|
||||
tags: (defaultTags.find((t) => Points.indexOf(t) >= 0)) ? defaultTags : [...defaultTags, 'Point']
|
||||
}
|
||||
|
||||
let line = []
|
||||
line.push(newItem.type)
|
||||
line.push(newItem.name)
|
||||
line.push(`"${newItem.label}"`)
|
||||
if (channelType.advanced) line[0] = '// ' + line[0] // comment the advanced channels by default
|
||||
line.push((newItem.category) ? `<${newItem.category}>` : '')
|
||||
line.push((newItem.groupNames.length) ? `(${newItem.groupNames.join(', ')})` : '')
|
||||
line.push((newItem.tags.length) ? `[${newItem.tags.map((t) => `"${t}"`).join(', ')}] ` : '')
|
||||
line.push(`{ channel="${channel.uid}" }`)
|
||||
lines.push(line)
|
||||
}
|
||||
|
||||
if (!lines.length) return def
|
||||
|
||||
let columnsWidths = []
|
||||
for (let c = 0; c < lines[0].length; c++) {
|
||||
columnsWidths.push(Math.max(...lines.map((l) => l[c].length)) + 1)
|
||||
}
|
||||
|
||||
def += '// Points:\n\n'
|
||||
lines.forEach((l) => {
|
||||
for (let c = 0; c < l.length; c++) {
|
||||
def += l[c] + ' '.repeat(columnsWidths[c] - l[c].length)
|
||||
}
|
||||
def += '\n'
|
||||
})
|
||||
|
||||
return def
|
||||
}
|
Loading…
Reference in New Issue