Skip to content

Commit e45644a

Browse files
committed
Thing Details: Use core's file-format service to display code in YAML and DSL
Signed-off-by: Jimmy Tanagra <[email protected]>
1 parent efe3fef commit e45644a

File tree

3 files changed

+106
-42
lines changed

3 files changed

+106
-42
lines changed

bundles/org.openhab.ui/web/src/components/config/controls/script-editor.vue

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,12 @@ export default {
172172
this.codemirror.closeHint()
173173
}
174174
},
175+
watch: {
176+
mode (newMode) {
177+
this.cmOptions.mode = this.translateMode(newMode)
178+
this.codemirror.setOption('mode', this.cmOptions.mode)
179+
}
180+
},
175181
methods: {
176182
translateMode (mode) {
177183
// Translations required for some special modes used in MainUI

bundles/org.openhab.ui/web/src/pages/settings/file-definition-mixin.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,12 @@ export default {
3535
THING: 'thing',
3636
ITEM: 'item'
3737
})
38+
this.MediaType = Object.freeze({
39+
YAML: 'application/yaml',
40+
THING_DSL: 'text/vnd.openhab.dsl.thing',
41+
ITEM_DSL: 'text/vnd.openhab.dsl.item',
42+
JSON: 'application/json'
43+
})
3844
},
3945
methods: {
4046
/**

bundles/org.openhab.ui/web/src/pages/settings/things/thing-details.vue

Lines changed: 94 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -195,12 +195,22 @@
195195
<f7-tab id="code" :tab-active="currentTab === 'code'">
196196
<f7-icon v-if="!editable" f7="lock" class="float-right margin"
197197
style="opacity:0.5; z-index: 4000; user-select: none;" size="50" color="gray" :tooltip="notEditableMsg" />
198-
<editor v-if="ready" class="thing-code-editor" mode="application/vnd.openhab.thing+yaml" :value="thingYaml"
198+
<editor v-if="ready" class="thing-code-editor" :mode="editorMode" :value="thingCode"
199199
:hint-context="{ thingType: thingType, channelTypes: channelTypes }" @input="onEditorInput"
200200
:read-only="!editable" />
201201
<!-- <pre class="yaml-message padding-horizontal" :class="[yamlError === 'OK' ? 'text-color-green' : 'text-color-red']">{{yamlError}}</pre> -->
202202
</f7-tab>
203203
</f7-tabs>
204+
<f7-toolbar bottom v-if="currentTab === 'code'">
205+
<f7-segmented tag="div">
206+
<f7-button outline small :active="codeType === 'YAML'" class="no-ripple" style="width: 5em;" @click="switchCodeType('YAML')">
207+
YAML
208+
</f7-button>
209+
<f7-button outline small :active="codeType === 'DSL'" class="no-ripple" style="width: 5em;" @click="switchCodeType('DSL')">
210+
DSL
211+
</f7-button>
212+
</f7-segmented>
213+
</f7-toolbar>
204214
</f7-page>
205215
</template>
206216

@@ -252,7 +262,7 @@ p.action-description
252262
.thing-code-editor.vue-codemirror
253263
display block
254264
top calc(var(--f7-navbar-height) + var(--f7-tabbar-height))
255-
height calc(100% - 2*var(--f7-navbar-height))
265+
height calc(100% - 2*var(--f7-navbar-height) - var(--f7-toolbar-height))
256266
width 100%
257267
258268
.item-title-content, .item-after-content
@@ -317,6 +327,9 @@ export default {
317327
'editor': () => import(/* webpackChunkName: "script-editor" */ '@/components/config/controls/script-editor.vue')
318328
},
319329
props: ['thingId'],
330+
created () {
331+
this.ThingMediaType = {YAML: this.MediaType.YAML, DSL: this.MediaType.THING_DSL}
332+
},
320333
data () {
321334
return {
322335
ready: false,
@@ -339,7 +352,9 @@ export default {
339352
configActionsByGroup: [],
340353
thingEnabled: true,
341354
eventSource: null,
342-
thingYaml: null,
355+
codeType: localStorage.getItem('openhab.ui:codeViewer.type') || 'YAML',
356+
thingCode: null,
357+
originalCode: null,
343358
notEditableMsg: 'This Thing is not editable because it has been provisioned from a file.',
344359
propertyTruncation: {}
345360
}
@@ -348,6 +363,12 @@ export default {
348363
editable () {
349364
return this.thing && this.thing.editable
350365
},
366+
editorMode () {
367+
if (this.codeType === 'DSL') {
368+
return 'text/x-java'
369+
}
370+
return 'application/vnd.openhab.thing+yaml'
371+
},
351372
pageTitle () {
352373
if (!this.ready) return ''
353374
return this.thing.label || this.thing.UID
@@ -422,19 +443,19 @@ export default {
422443
}
423444
},
424445
onEditorInput (value) {
425-
this.thingYaml = value
446+
this.thingCode = value
447+
this.dirty = this.configDirty || this.thingDirty || this.originalCode !== this.thingCode
426448
},
427449
switchTab (tab) {
428450
if (this.currentTab === tab) return
429451
if (this.currentTab === 'code') {
430-
const previousYaml = this.toYaml()
431-
if (this.thingYaml !== previousYaml && this.fromYaml()) {
432-
this.save()
452+
if (this.originalCode !== this.thingCode) {
453+
this.fromCode()
433454
}
434455
}
435456
this.currentTab = tab
436457
if (this.currentTab === 'code') {
437-
this.thingYaml = this.toYaml()
458+
this.toCode(this.codeType)
438459
}
439460
},
440461
/**
@@ -539,13 +560,12 @@ export default {
539560
}
540561
})
541562
},
542-
save (saveThing) {
563+
save (checkCode = true) {
543564
if (!this.ready || !this.editable) return
544565
545-
if (this.currentTab === 'code') {
546-
if (!this.fromYaml()) {
547-
return
548-
}
566+
if (checkCode && this.currentTab === 'code') {
567+
this.fromCode(() => this.save(false))
568+
return
549569
}
550570
551571
let endpoint, payload, successMessage
@@ -771,7 +791,7 @@ export default {
771791
})
772792
},
773793
onChannelsUpdated (save) {
774-
if (save) this.save(true)
794+
if (save) this.save()
775795
if (!this.eventSource) this.startEventSource()
776796
},
777797
unlinkAll (removeItems) {
@@ -858,37 +878,69 @@ export default {
858878
this.$oh.sse.close(this.eventSource)
859879
this.eventSource = null
860880
},
861-
toYaml () {
862-
const editableThing = {
863-
UID: this.thing.UID,
864-
label: this.thing.label,
865-
thingTypeUID: this.thing.thingTypeUID,
866-
configuration: this.thing.configuration
881+
switchCodeType (type) {
882+
if (this.codeType === type) return
883+
if (this.editable) {
884+
this.fromCode(() => {
885+
this.toCode(type, () => {
886+
localStorage.setItem('openhab.ui:codeViewer.type', type)
887+
this.codeType = type
888+
})
889+
})
890+
} else {
891+
this.toCode(type, () => {
892+
localStorage.setItem('openhab.ui:codeViewer.type', type)
893+
this.codeType = type
894+
})
867895
}
868-
869-
if (this.thing.bridgeUID) editableThing.bridgeUID = this.thing.bridgeUID
870-
if (this.thing.location) editableThing.location = this.thing.location
871-
872-
const editableChannels = []
873-
874-
for (const channel of this.thing.channels) {
875-
const editableChannel = {
876-
id: channel.id,
877-
channelTypeUID: channel.channelTypeUID,
878-
label: channel.label,
879-
description: channel.description,
880-
configuration: channel.configuration
881-
}
882-
editableChannels.push(editableChannel)
896+
},
897+
toCode (codeType, successCallback) {
898+
const mediaType = this.ThingMediaType[codeType]
899+
console.log('toCode', mediaType)
900+
const payload = { things: [this.thing] }
901+
this.$oh.api.postPlain('/rest/file-format/create', JSON.stringify(payload), null, 'application/json', { accept: mediaType })
902+
.then((code) => {
903+
if (codeType === 'YAML') {
904+
// skip version:, things: and UID: lines, and unindent lines
905+
code = code.split('\n').slice(3).map(line => line.replace(/^\s{4}/, '')).join('\n')
906+
}
907+
this.thingCode = code
908+
this.originalCode = cloneDeep(code)
909+
if (successCallback) {
910+
successCallback()
911+
}
912+
})
913+
.catch((err) => {
914+
this.$f7.dialog.alert(`Error creating ${codeType}: ${err}`).open()
915+
})
916+
},
917+
fromCode (successCallback) {
918+
const mediaType = this.ThingMediaType[this.codeType]
919+
let payload = null
920+
if (this.codeType === 'YAML') {
921+
const indentedCode = this.thingCode.split('\n').map(line => ' '.repeat(4) + line).join('\n')
922+
payload = `version: 2\nthings:\n ${this.thing.UID}:\n${indentedCode}`
923+
} else {
924+
payload = this.thingCode
883925
}
884-
885-
if (editableChannels.length > 0) editableThing.channels = editableChannels
886-
887-
return YAML.stringify(editableThing)
926+
this.$oh.api.postPlain('/rest/file-format/parse', payload, null, mediaType, { accept: 'application/json' })
927+
.then((data) => {
928+
data = JSON.parse(data)
929+
if (data.things && data.things.length > 0) {
930+
const updatedThing = data.things[0]
931+
this.updateThing(updatedThing)
932+
if (successCallback) {
933+
successCallback()
934+
}
935+
} else {
936+
this.$f7.dialog.alert('Error parsing ' + this.codeType + ': no things found').open()
937+
}
938+
})
939+
.catch((err) => {
940+
this.$f7.dialog.alert(`Error parsing ${this.codeType}: ${err}`).open()
941+
})
888942
},
889-
fromYaml () {
890-
const updatedThing = YAML.parse(this.thingYaml)
891-
943+
updateThing (updatedThing) {
892944
const isExtensible = (channel, thingType) => {
893945
if (!channel || !channel.channelTypeUID) return false
894946
const bindingId = thingType.UID.split(':')[0]

0 commit comments

Comments
 (0)