Checkpoint

This commit is contained in:
Magnus Åhall 2026-02-23 09:39:52 +01:00
parent 4637689db4
commit 5112113aae
4 changed files with 104 additions and 40 deletions

53
dns.go
View file

@ -104,19 +104,17 @@ func BuildRecordsTree(records []DNSRecord) *DomainPart {
return topPart return topPart
} }
func (dp *DomainPart) ToHTML(parts []string) string { type HTMLElement struct {
html := ""
/*
var lines []struct {
Header bool Header bool
HTML string HTML string
} }
*/
func (dp *DomainPart) ToHTMLElements(parts []string, idFrom int) []HTMLElement {
var lines []HTMLElement
sortedParts := slices.Sorted(maps.Keys(dp.Subparts)) sortedParts := slices.Sorted(maps.Keys(dp.Subparts))
for _, part := range sortedParts { for i, part := range sortedParts {
subpart := dp.Subparts[part] subpart := dp.Subparts[part]
newParts := append(parts, part) newParts := append(parts, part)
@ -132,32 +130,41 @@ func (dp *DomainPart) ToHTML(parts []string) string {
mostSpecificPart += "." mostSpecificPart += "."
} }
var subHTML string
if len(subpart.Subparts) == 0 { if len(subpart.Subparts) == 0 {
html += fmt.Sprintf( html := fmt.Sprintf(
`<div class="record" style="margin-left: %dpx" data-top="%s"><span>%s</span><span>%s</span></div>`, `
len(newParts)*16, <div class="record" style="padding-left: %dpx" data-i="%d" data-top="%s"><span>%s</span><span>%s</span></div>
restPart, <div class="type" data-i="%d">hum</div>
`,
len(newParts)*32,
idFrom + i, // data-i
restPart, // data-top
mostSpecificPart, mostSpecificPart,
restPart, restPart,
idFrom + i,
) )
lines = append(lines, HTMLElement{Header: false, HTML: html})
} else { } else {
subHTML = subpart.ToHTML(newParts) html := fmt.Sprintf(`
html += fmt.Sprintf(` <div class="top" data-i="%d" data-top="%s" data-self="%s" style="padding-left: %dpx">
<div class="top" data-top="%s" style="margin-left: %dpx"> <span>%s</span><span>%s</span>
<div class="fqdn">%s</div>
</div> </div>
<div data-top="%s" class="records">%s</div> <div class="type" data-i="%d"></div>
`, `,
fqdn, idFrom + i, // data-i
len(newParts)*16, restPart, // data-top
fqdn, fqdn, // data-self
fqdn, len(newParts)*32, // margin-left
subHTML, mostSpecificPart, // innerText
restPart,
idFrom + i,
) )
lines = append(lines, HTMLElement{Header: true, HTML: html})
subLines := subpart.ToHTMLElements(newParts, idFrom + i)
lines = append(lines, subLines...)
} }
} }
return html return lines
} }

View file

@ -18,21 +18,33 @@ body {
.records-tree { .records-tree {
display: grid; display: grid;
grid-template-columns: min-content 1fr;
white-space: nowrap;
.fqdn, .record { .top, .record, .type {
border-bottom: 1px solid #aaa; border-bottom: 1px solid #ccc;
padding: 4px 0px; padding: 4px 0px;
} }
.top { .top {
font-weight: bold; font-weight: bold;
background-color: #f8f8f8;
span:first-child {
/*color: #004680;*/
} }
&>.top { span:last-child {
color: #444;
font-weight: normal;
}
}
.top + .type {
background-color: #f8f;
} }
.record { .record {
display: none; /*display: none;*/
font-weight: normal; font-weight: normal;
color: #444; color: #444;
@ -48,4 +60,8 @@ body {
color: #888; color: #888;
} }
} }
.record + .type {
color: #f0f;
}
} }

View file

@ -1,20 +1,48 @@
export class Application { export class Application {
constructor() { constructor() {
this.addTopHandlers() this.addTopHandlers()
this.moveRecords()
}
moveRecords() {
const records = Array.from(document.querySelectorAll('.record'))
records.sort((a, b) => {
if (a.innerText < b.innerText) return 1
if (a.innerText > b.innerText) return -1
return 0
})
for (const r of records) {
const subTops = document.querySelectorAll(`.top[data-top="${r.dataset.top}"] + .type`)
if (subTops === null) {
continue
}
let lastSubTop = subTops.item(subTops.length - 1)
if (lastSubTop === null) {
lastSubTop = document.querySelector(`.top[data-self="${r.dataset.top}"] + .type`)
}
if (lastSubTop !== null) {
const other = Array.from(document.querySelectorAll(`[data-i="${r.dataset.i}"]`))
console.log(other)
lastSubTop.after(...other)
}
}
} }
addTopHandlers() { addTopHandlers() {
for (const top of document.querySelectorAll('.top .fqdn')) for (const top of document.querySelectorAll('.top'))
top.addEventListener('click', event => this.handlerTop(event)) top.addEventListener('click', event => this.handlerTop(event))
} }
handlerTop(event) { handlerTop(event) {
const fqdn = event.target const topEl = event.target.closest('.top')
const topEl = fqdn.closest('.top')
const records = document.querySelectorAll(`.record[data-top="${topEl.dataset.top}"]`) const records = document.querySelectorAll(`.record[data-top="${topEl.dataset.self}"]`)
console.log(`.record[data-top="${topEl.dataset.top}"]`) for (const r of records) {
console.log(topEl.dataset.top, records)
for (const r of records)
r.classList.toggle('show') r.classList.toggle('show')
} }
} }
}

View file

@ -67,8 +67,21 @@ func rootHandler(w http.ResponseWriter, r *http.Request) {
data["DNSRecords"] = entries data["DNSRecords"] = entries
tree := BuildRecordsTree(entries) tree := BuildRecordsTree(entries)
htmlTree := tree.ToHTML([]string{}) htmlElements := tree.ToHTMLElements([]string{}, 0)
data["Tree"] = template.HTML(htmlTree)
var html string
for _, el := range htmlElements {
if el.Header {
html += el.HTML
}
}
for _, el := range htmlElements {
if !el.Header {
html += el.HTML
}
}
data["Tree"] = template.HTML(html)
j, _ := json.Marshal(tree) j, _ := json.Marshal(tree)
os.WriteFile("/tmp/tree.json", j, 0644) os.WriteFile("/tmp/tree.json", j, 0644)