Handling of data types

This commit is contained in:
Magnus Åhall 2025-07-10 10:39:33 +02:00
parent 9d50b97436
commit 8988720c0e
6 changed files with 331 additions and 18 deletions

View file

@ -316,3 +316,6 @@ dialog#connection-data div.button {
#editor-type-schema img {
height: 32px;
}
#editor-type-schema img.saving {
filter: invert(0.7) sepia(0.5) hue-rotate(0deg) saturate(600%) brightness(0.75);
}

View file

@ -108,8 +108,19 @@ export class App {
break
case 'TYPE_EDIT':
const editor = new TypeSchemaEditor(event.detail.Type)
document.getElementById('editor-type-schema').replaceChildren(editor.render())
const typeID = event.detail
fetch(`/types/${typeID}`)
.then(data => data.json())
.then(json => {
if (!json.OK) {
showError(json.Error)
return
}
const editor = new TypeSchemaEditor(json.Type)
document.getElementById('editor-type-schema').replaceChildren(editor.render())
})
.catch(err => showError(err))
break
default:
@ -695,6 +706,13 @@ export class TypesList {
render() {// {{{
const div = document.createElement('div')
const create = document.createElement('img')
create.setAttribute('src', `/images/${_VERSION}/node_modules/@mdi/svg/svg/plus-box.svg`)
create.style.height = '32px'
create.style.cursor = 'pointer';
create.addEventListener('click', () => this.createType())
div.appendChild(create)
this.types.sort(_app.typeSort)
let prevGroup = null
@ -714,28 +732,50 @@ export class TypesList {
const tDiv = document.createElement('div')
tDiv.classList.add('type')
tDiv.innerHTML = `
<div class="img"><img src="/images/${_VERSION}/node_modules/@mdi/svg/svg/file-document-check-outline.svg" /></div>
<div class="img"><img src="/images/${_VERSION}/node_modules/@mdi/svg/svg/${t.Schema.icon}.svg" /></div>
<div class="title">${t.Schema.title || t.Name}</div>
`
tDiv.addEventListener('click', () => mbus.dispatch('TYPE_EDIT', { Type: t }))
tDiv.addEventListener('click', () => mbus.dispatch('TYPE_EDIT', t.ID))
div.appendChild(tDiv)
}
return div
}// }}}
createType() {// {{{
const name = prompt("Type name")
if (name === null)
return
fetch(`/types/create`, {
method: 'POST',
body: JSON.stringify({ name }),
})
.then(data => data.json())
.then(json => {
if (!json.OK) {
showError(json.Error)
return
}
_app.typesList.fetchTypes().then(() => {
mbus.dispatch('TYPES_LIST_FETCHED')
mbus.dispatch('TYPE_EDIT', json.Type.ID)
})
})
.catch(err => showError(err))
}// }}}
}
class TypeSchemaEditor {
constructor(dataType) {
constructor(dataType) {// {{{
this.type = dataType
}
render() {
}// }}}
render() {// {{{
const tmpl = document.createElement('template')
tmpl.innerHTML = `
<div>
<div style="float: left;" class="label">${this.type.Schema.title}</div>
<div style="float: right;"><img src="/images/${_VERSION}/node_modules/@mdi/svg/svg/content-save.svg" /></div>
<div style="float: right;"><img class="save" src="/images/${_VERSION}/node_modules/@mdi/svg/svg/content-save.svg" /></div>
</div>
<div style="clear: both;">
<input type="text" class="name">
@ -743,13 +783,60 @@ class TypeSchemaEditor {
<textarea class="type-schema"></textarea>
`
tmpl.content.querySelector('.name').value = this.type.Name
this.textarea = tmpl.content.querySelector('textarea')
this.textarea.value = JSON.stringify(this.type.Schema, null, 4)
this.textarea.addEventListener('keydown', event => {
if (!event.ctrlKey || event.key !== 's')
return
event.stopPropagation()
event.preventDefault()
this.save()
})
const textarea = tmpl.content.querySelector('textarea')
textarea.value = JSON.stringify(this.type.Schema, null, 4)
this.name = tmpl.content.querySelector('.name')
this.name.value = this.type.Name
this.img_save = tmpl.content.querySelector('img.save')
this.img_save.addEventListener('click', () => this.save())
return tmpl.content
}
}// }}}
save() {// {{{
const req = {
Name: this.name.value,
Schema: this.textarea.value,
}
const start_update = Date.now()
this.img_save.classList.add('saving')
fetch(`/types/update/${this.type.ID}`, {
method: 'POST',
body: JSON.stringify(req),
})
.then(data => data.json())
.then(json => {
if (!json.OK) {
showError(json.Error)
return
}
const time_left = 100 - (Date.now() - start_update)
setTimeout(() => {
this.img_save.classList.remove('saving')
this.refreshTypeUI()
}, Math.max(time_left, 0))
})
.catch(err => showError(err))
}// }}}
async refreshTypeUI() {// {{{
_app.typesList.fetchTypes().then(() => {
mbus.dispatch('TYPES_LIST_FETCHED')
mbus.dispatch('TYPE_EDIT', this.type.ID)
})
}// }}}
}
class ConnectedNodes {

View file

@ -416,5 +416,9 @@ dialog#connection-data {
img {
height: 32px;
&.saving {
filter: invert(.7) sepia(.5) hue-rotate(0deg) saturate(600%) brightness(0.75);
}
}
}