WIP on web UI:

Make selected items show as selected.
Break out XML file handling so the tree component could just handle elements and leave the XML parsing to the parent.
Sort mods by name, not id.
This commit is contained in:
Daniel Ceregatti 2023-11-03 16:13:14 -07:00
parent 788bac39a4
commit b8b0a43df1
5 changed files with 79 additions and 107 deletions

View file

@ -1,6 +1,6 @@
<script setup>
import { useFetch } from "@vueuse/core"
import xmlTree from '@/components/XmlTree.vue'
import XmlFile from '@/components/XmlFile.vue'
import { useAppStore } from '@/stores/app.js'
const store = useAppStore()
import { config } from '@/config'
@ -29,7 +29,7 @@ const { data, error } = useFetch(() => config.baseUrl + `/mod/${store.modId}`, {
<ul>
<li v-for="info in data.customXML">
<a
:class="'simulink xmlfile ' + info.name"
:class="'simulink xmlfile ' + (store.modFile === info.name ? 'active' : '')"
@click="store.modFile=info.name"
>
{{ info.name }}
@ -39,8 +39,8 @@ const { data, error } = useFetch(() => config.baseUrl + `/mod/${store.modId}`, {
</div>
</div>
<div class="col-1"></div>
<div v-if="store.modFile">
<xml-tree :file="store.modFile" :mod-id="store.modId" />
<div>
<XmlFile />
</div>
</div>
</div>

View file

@ -26,7 +26,7 @@ const { data, error } = useFetch(config.baseUrl + '/mods', {
<th>Mod Name</th>
</tr>
<template
v-for="mod in data.mods"
v-for="mod in data.mods.sort( (a,b) => { return a.name.localeCompare(b.name) } )"
>
<tr>
<td>
@ -38,7 +38,12 @@ const { data, error } = useFetch(config.baseUrl + '/mods', {
</a>
</td>
<td>
<a class="simulink" @click="store.modId=parseInt(mod.id)">{{ mod.name }}</a>
<a
:class="'simulink' + (store.modId === parseInt(mod.id) ? ' active' : '')"
@click="store.modFile='';store.modId=parseInt(mod.id)"
>
{{ mod.name }}
</a>
</td>
</tr>
</template>

View file

@ -0,0 +1,28 @@
<script setup>
import { useFetch } from '@vueuse/core'
import { config } from '@/config'
import { useAppStore } from '@/stores/app.js'
import XmlTree from '@/components/XmlTree.vue'
const store = useAppStore()
const { data, error } = await useFetch(() => config.baseUrl + `/mod/${store.modId}/${store.modFile}`, {
immediate: false,
refetch: true,
afterFetch(response) {
const parser = new DOMParser()
try {
response.data = parser.parseFromString(response.data, "text/xml").documentElement
} catch(e) {
console.error(e)
response.error = e
}
return response
}
}).get()
</script>
<template>
<div v-if="error">{{ error }}</div>
<div v-else-if="data">
<XmlTree :element="data" :depth="0" />
</div>
</template>

View file

@ -1,114 +1,49 @@
<template>
<div
v-if="elem.nodeType === 1 && isText"
:style="'padding-left: ' + (depth * 10) + 'px'"
@click="collapse"
>
<span class="xml-tree-tag">&lt;{{elem.nodeName}}</span>
<span v-if="elem.hasAttributes()" v-for="attribute in elem.attributes">
<span class="xml-tree-attr">&nbsp;{{attribute.name}}</span>
<span>=</span>
<span class="xml-tree-attr">"{{attribute.value}}"</span>
</span>
<span class="xml-tree-tag">></span>
<span>{{this.children[0].data.trim()}}</span>
<span class="xml-tree-tag">&lt;/{{elem.nodeName}}></span>
</div>
<div v-else :style="'padding-left: ' + (depth * 10) + 'px'">
<span v-if="elem.nodeType === 1" class="d-flex">
<span
v-if="elem.children.length > 0"
class="bi-dash simulink text-center"
@click="collapse"
/>
<span v-else></span>
<span class="xml-tree-tag">&lt;{{elem.nodeName}}</span>
<span v-if="elem.hasAttributes()" v-for="attribute in elem.attributes">
<span class="xml-tree-attr">&nbsp;{{attribute.name}}</span>
<span>=</span>
<span class="xml-tree-attr">"{{attribute.value}}"</span>
</span>
<span v-if="elem.children.length === 0" class="xml-tree-tag">&nbsp;/></span>
<span v-else class="xml-tree-tag">></span>
</span>
<span v-if="elem.nodeType === 3">{{elem.data.trim()}}</span>
<div v-for="child in children">
<xml-tree v-if="child.nodeType !== 8" :element="child" :d="depth" />
</div>
<span
v-if="elem.nodeType === 1 && elem.children.length > 0"
style="padding-left: -10px"
>
<span style="padding-left: 20px" class="xml-tree-tag">&lt;/{{elem.nodeName}}></span>
</span>
</div>
</template>
<script>
import { useFetch } from '@vueuse/core'
import { config } from '@/config'
export default {
name: "xmlTree",
props: {
d: {
type: Number,
default: 0
},
element: {
type: [Element, Text],
default: undefined
},
file: {
type: String,
default: ''
},
modId: {
type: Number,
default: 0
<script setup>
const props = defineProps({
depth: Number,
element: [Element, Text],
})
function collapse(e) {
console.log(e)
// e.children?.forEach(x => x.classList?.add("d-none"))
}
},
data() {
return {
depth: 1
}
},
methods: {
collapse() {
this.children.forEach(x => x.classList?.add("d-none"))
},
log(message) {
console.log(message)
}
},
computed: {
async elem() {
this.depth = parseInt(this.d) + 1
if (this.element) {
return this.element
} else if(this.file) {
const { data } = await useFetch(config.baseUrl + `/mod/${this.modId}/${this.file}`)
const parser = new DOMParser()
const xmlDoc = parser.parseFromString(data, "text/xml")
return xmlDoc.documentElement
}
},
children() {
function children(e) {
let children = []
let node = this.elem.firstChild
let node = e.firstChild
while (node) {
children.push(node)
node = node.nextSibling
}
return children
},
isText() {
if (this.children.length === 1) {
if (this.children[0].nodeType === 3) {
return true
}
}
return false
}
}
}
</script>
<template>
<div v-if="props.element.nodeType === 1" :style="'padding-left: ' + (props.depth * 10) + 'px'">
<span class="d-flex">
<span
v-if="props.element.children.length > 0"
class="bi-dash simulink text-center"
@click="collapse"
/>
<span>&lt;{{props.element.nodeName}}</span>
<span v-if="props.element.hasAttributes()" v-for="attribute in props.element.attributes">
<span>&nbsp;{{attribute.name}}</span>
<span>=</span>
<span>"{{attribute.value}}"</span>
</span>
<span v-if="props.element.children.length === 0">&nbsp;/</span>
<span>></span>
</span>
<span v-for="child in children(props.element)">
<XmlTree v-if="child.nodeType !== 8" :element="child" :depth="props.depth + 1" />
</span>
<span
v-if="props.element.nodeType === 1"
style="padding-left: -10px"
>
<span>&lt;/{{props.element.nodeName}}></span>
</span>
</div>
<span v-if="props.element.nodeType === 3">{{props.element.data.trim()}}</span>
</template>

View file

@ -7,11 +7,15 @@ th, td {
padding-right: 10px
}
.active {
background-color: cyan;
}
.simulink {
cursor: pointer;
text-underline: blue;
}
.simulink:hover {
background-color: cyan;
background-color: green;
}