mirror of
https://ceregatti.org/git/daniel/dayzdockerserver.git
synced 2025-05-06 14:21:18 +00:00
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:
parent
788bac39a4
commit
b8b0a43df1
5 changed files with 79 additions and 107 deletions
|
@ -1,6 +1,6 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { useFetch } from "@vueuse/core"
|
import { useFetch } from "@vueuse/core"
|
||||||
import xmlTree from '@/components/XmlTree.vue'
|
import XmlFile from '@/components/XmlFile.vue'
|
||||||
import { useAppStore } from '@/stores/app.js'
|
import { useAppStore } from '@/stores/app.js'
|
||||||
const store = useAppStore()
|
const store = useAppStore()
|
||||||
import { config } from '@/config'
|
import { config } from '@/config'
|
||||||
|
@ -29,7 +29,7 @@ const { data, error } = useFetch(() => config.baseUrl + `/mod/${store.modId}`, {
|
||||||
<ul>
|
<ul>
|
||||||
<li v-for="info in data.customXML">
|
<li v-for="info in data.customXML">
|
||||||
<a
|
<a
|
||||||
:class="'simulink xmlfile ' + info.name"
|
:class="'simulink xmlfile ' + (store.modFile === info.name ? 'active' : '')"
|
||||||
@click="store.modFile=info.name"
|
@click="store.modFile=info.name"
|
||||||
>
|
>
|
||||||
{{ info.name }}
|
{{ info.name }}
|
||||||
|
@ -39,8 +39,8 @@ const { data, error } = useFetch(() => config.baseUrl + `/mod/${store.modId}`, {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-1"></div>
|
<div class="col-1"></div>
|
||||||
<div v-if="store.modFile">
|
<div>
|
||||||
<xml-tree :file="store.modFile" :mod-id="store.modId" />
|
<XmlFile />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -26,7 +26,7 @@ const { data, error } = useFetch(config.baseUrl + '/mods', {
|
||||||
<th>Mod Name</th>
|
<th>Mod Name</th>
|
||||||
</tr>
|
</tr>
|
||||||
<template
|
<template
|
||||||
v-for="mod in data.mods"
|
v-for="mod in data.mods.sort( (a,b) => { return a.name.localeCompare(b.name) } )"
|
||||||
>
|
>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
|
@ -38,7 +38,12 @@ const { data, error } = useFetch(config.baseUrl + '/mods', {
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
<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>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</template>
|
</template>
|
||||||
|
|
28
web/docroot/src/components/XmlFile.vue
Normal file
28
web/docroot/src/components/XmlFile.vue
Normal 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>
|
|
@ -1,114 +1,49 @@
|
||||||
<template>
|
<script setup>
|
||||||
<div
|
const props = defineProps({
|
||||||
v-if="elem.nodeType === 1 && isText"
|
depth: Number,
|
||||||
:style="'padding-left: ' + (depth * 10) + 'px'"
|
element: [Element, Text],
|
||||||
@click="collapse"
|
})
|
||||||
>
|
function collapse(e) {
|
||||||
<span class="xml-tree-tag"><{{elem.nodeName}}</span>
|
console.log(e)
|
||||||
<span v-if="elem.hasAttributes()" v-for="attribute in elem.attributes">
|
// e.children?.forEach(x => x.classList?.add("d-none"))
|
||||||
<span class="xml-tree-attr"> {{attribute.name}}</span>
|
}
|
||||||
<span>=</span>
|
function children(e) {
|
||||||
<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"></{{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"><{{elem.nodeName}}</span>
|
|
||||||
<span v-if="elem.hasAttributes()" v-for="attribute in elem.attributes">
|
|
||||||
<span class="xml-tree-attr"> {{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"> /></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"></{{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
|
|
||||||
}
|
|
||||||
},
|
|
||||||
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() {
|
|
||||||
let children = []
|
let children = []
|
||||||
let node = this.elem.firstChild
|
let node = e.firstChild
|
||||||
while (node) {
|
while (node) {
|
||||||
children.push(node)
|
children.push(node)
|
||||||
node = node.nextSibling
|
node = node.nextSibling
|
||||||
}
|
}
|
||||||
return children
|
return children
|
||||||
},
|
|
||||||
isText() {
|
|
||||||
if (this.children.length === 1) {
|
|
||||||
if (this.children[0].nodeType === 3) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</script>
|
</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><{{props.element.nodeName}}</span>
|
||||||
|
<span v-if="props.element.hasAttributes()" v-for="attribute in props.element.attributes">
|
||||||
|
<span> {{attribute.name}}</span>
|
||||||
|
<span>=</span>
|
||||||
|
<span>"{{attribute.value}}"</span>
|
||||||
|
</span>
|
||||||
|
<span v-if="props.element.children.length === 0"> /</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></{{props.element.nodeName}}></span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<span v-if="props.element.nodeType === 3">{{props.element.data.trim()}}</span>
|
||||||
|
</template>
|
||||||
|
|
|
@ -7,11 +7,15 @@ th, td {
|
||||||
padding-right: 10px
|
padding-right: 10px
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.active {
|
||||||
|
background-color: cyan;
|
||||||
|
}
|
||||||
|
|
||||||
.simulink {
|
.simulink {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
text-underline: blue;
|
text-underline: blue;
|
||||||
}
|
}
|
||||||
|
|
||||||
.simulink:hover {
|
.simulink:hover {
|
||||||
background-color: cyan;
|
background-color: green;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue