1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
import { templated } from 'atlibs/component/index.js'
const Base = await templated(new URL('./marque-dns.html', import.meta.url))
const cell = (text) => Object.assign(document.createElement('td'), { textContent: text ?? '' })
const button = (text, onclick) => Object.assign(document.createElement('button'), { type: 'button', textContent: text, onclick })
// Markup in .html; this sends events up (login, logout, view, open, dns-change) and renders the cubit's state.
customElements.define('marque-dns', class extends Base {
connectedCallback() {
super.connectedCallback()
const $ = (selector) => this.querySelector(selector)
this.send = (name, detail) => this.dispatchEvent(new CustomEvent(name, { bubbles: true, detail }))
$('.login').onsubmit = (e) => (e.preventDefault(), this.send('login', e.target.elements.handle.value))
$('.view').onsubmit = (e) => (e.preventDefault(), this.send('view', e.target.elements.did.value.trim()))
$('.logout').onclick = () => this.send('logout')
$('.cancel').onclick = () => this.edit(null)
$('.record').onsubmit = (e) => {
e.preventDefault()
const f = Object.fromEntries(new FormData(e.target))
const set = { ttl: f.ttl, priority: f.priority }
if (f.entry === 'create_record') this.send('dns-change', { entry: f.entry, fields: { name: f.newName, type: f.newType, value: f.newValue, ...set } })
else this.send('dns-change', { entry: f.entry, fields: { name: f.name, type: f.type, value: f.value, newName: f.newName, newValue: f.newValue, ...set } })
}
}
// Fill the form to change a record, or (null) back to adding one. The type of a record stays its own.
edit(record) {
const form = this.querySelector('.record')
const el = form.elements // not form.name: that is the form's own name attribute
form.reset()
el.entry.value = record ? 'update_record' : 'create_record'
el.newType.disabled = !!record
form.querySelector('h3').textContent = record ? `Change ${record.recordType} ${record.name}` : 'Add a record'
form.querySelector('.save').textContent = record ? 'Save' : 'Add'
form.querySelector('.cancel').hidden = !record
if (!record) return
el.name.value = el.newName.value = record.name
el.type.value = el.newType.value = record.recordType
el.value.value = el.newValue.value = record.value
el.ttl.value = record.ttl ?? ''
el.priority.value = record.priority ?? ''
}
render({ session, did, error, domains, domain, zone, change }) {
const $ = (selector) => this.querySelector(selector)
const signedIn = session === 'signed-in'
$('.login').hidden = $('.view').hidden = session !== 'signed-out'
$('.who').hidden = !signedIn
$('.who span').textContent = signedIn ? `Signed in as ${did}` : ''
$('.error').textContent = error ?? domains.error ?? zone.error ?? ''
const list = $('.domains')
list.replaceChildren(...(domains.result?.domains ?? []).map((d) => {
const item = document.createElement('li')
item.append(button(d.domain, () => this.send('open', d.domain)), ` ${d.status ?? ''}${d.expiresAt ? `, expires ${d.expiresAt.slice(0, 10)}` : ''}`)
return item
}))
if (domains.status === 'done' && !list.childElementCount) list.textContent = 'No at.marque.domain records in this account. Register a domain at marque.at.'
$('.zone').hidden = !domain
$('.zone-name').textContent = domain ?? ''
$('.record').hidden = !signedIn
$('.record .save').disabled = change.status === 'busy'
$('tbody').replaceChildren(...(zone.result?.records ?? []).map((r) => {
const row = document.createElement('tr')
const actions = document.createElement('td')
if (signedIn) {
actions.append(
button('Edit', () => this.edit(r)),
button('Remove', () => confirm(`Remove ${r.recordType} ${r.name} ${r.value}?`) && this.send('dns-change', { entry: 'delete_record', fields: { name: r.name, type: r.recordType, value: r.value } })),
)
}
row.append(cell(r.name), cell(r.recordType), cell(r.value), cell(String(r.ttl ?? '')), cell(r.priority === undefined ? '' : String(r.priority)), actions)
return row
}))
if (change.status === 'done') this.edit(null)
$('.out').textContent = change.error ?? (change.result ? `Saved: ${change.result.records} records, ${change.result.uri}` : '')
}
})