From 5112113aaec0290057a1f6daeb99f659b667874c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Magnus=20=C3=85hall?= Date: Mon, 23 Feb 2026 09:39:52 +0100 Subject: [PATCH] Checkpoint --- dns.go | 57 +++++++++++++++++++++++++------------------- static/css/index.css | 26 ++++++++++++++++---- static/js/dns.mjs | 44 +++++++++++++++++++++++++++------- webserver.go | 17 +++++++++++-- 4 files changed, 104 insertions(+), 40 deletions(-) diff --git a/dns.go b/dns.go index dfcd0b3..a88ded2 100644 --- a/dns.go +++ b/dns.go @@ -104,19 +104,17 @@ func BuildRecordsTree(records []DNSRecord) *DomainPart { return topPart } -func (dp *DomainPart) ToHTML(parts []string) string { - html := "" +type HTMLElement struct { + Header bool + HTML string +} - /* - var lines []struct { - Header bool - HTML string - } - */ +func (dp *DomainPart) ToHTMLElements(parts []string, idFrom int) []HTMLElement { + var lines []HTMLElement sortedParts := slices.Sorted(maps.Keys(dp.Subparts)) - for _, part := range sortedParts { + for i, part := range sortedParts { subpart := dp.Subparts[part] newParts := append(parts, part) @@ -132,32 +130,41 @@ func (dp *DomainPart) ToHTML(parts []string) string { mostSpecificPart += "." } - var subHTML string if len(subpart.Subparts) == 0 { - html += fmt.Sprintf( - `
%s%s
`, - len(newParts)*16, - restPart, + html := fmt.Sprintf( + ` +
%s%s
+
hum
+ `, + len(newParts)*32, + idFrom + i, // data-i + restPart, // data-top mostSpecificPart, restPart, + idFrom + i, ) + lines = append(lines, HTMLElement{Header: false, HTML: html}) } else { - subHTML = subpart.ToHTML(newParts) - html += fmt.Sprintf(` -
-
%s
+ html := fmt.Sprintf(` +
+ %s%s
-
%s
+
`, - fqdn, - len(newParts)*16, - fqdn, - fqdn, - subHTML, + idFrom + i, // data-i + restPart, // data-top + fqdn, // data-self + len(newParts)*32, // margin-left + 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 } diff --git a/static/css/index.css b/static/css/index.css index a671edf..f51925b 100644 --- a/static/css/index.css +++ b/static/css/index.css @@ -18,21 +18,33 @@ body { .records-tree { display: grid; + grid-template-columns: min-content 1fr; + white-space: nowrap; - .fqdn, .record { - border-bottom: 1px solid #aaa; + .top, .record, .type { + border-bottom: 1px solid #ccc; padding: 4px 0px; } .top { font-weight: bold; - } + background-color: #f8f8f8; - &>.top { + span:first-child { + /*color: #004680;*/ + } + + span:last-child { + color: #444; + font-weight: normal; + } + } + .top + .type { + background-color: #f8f; } .record { - display: none; + /*display: none;*/ font-weight: normal; color: #444; @@ -48,4 +60,8 @@ body { color: #888; } } + + .record + .type { + color: #f0f; + } } diff --git a/static/js/dns.mjs b/static/js/dns.mjs index 99685cf..b3dc270 100644 --- a/static/js/dns.mjs +++ b/static/js/dns.mjs @@ -1,20 +1,48 @@ export class Application { constructor() { 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() { - for (const top of document.querySelectorAll('.top .fqdn')) - top.addEventListener('click', event=>this.handlerTop(event)) + for (const top of document.querySelectorAll('.top')) + top.addEventListener('click', event => this.handlerTop(event)) } handlerTop(event) { - const fqdn = event.target - const topEl = fqdn.closest('.top') - const records = document.querySelectorAll(`.record[data-top="${topEl.dataset.top}"]`) - console.log(`.record[data-top="${topEl.dataset.top}"]`) - console.log(topEl.dataset.top, records) - for (const r of records) + const topEl = event.target.closest('.top') + + const records = document.querySelectorAll(`.record[data-top="${topEl.dataset.self}"]`) + for (const r of records) { r.classList.toggle('show') + } } } diff --git a/webserver.go b/webserver.go index e67aba0..e555f39 100644 --- a/webserver.go +++ b/webserver.go @@ -67,8 +67,21 @@ func rootHandler(w http.ResponseWriter, r *http.Request) { data["DNSRecords"] = entries tree := BuildRecordsTree(entries) - htmlTree := tree.ToHTML([]string{}) - data["Tree"] = template.HTML(htmlTree) + htmlElements := tree.ToHTMLElements([]string{}, 0) + + 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) os.WriteFile("/tmp/tree.json", j, 0644)