-
Notifications
You must be signed in to change notification settings - Fork 78
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refactor web frontend and remove unnecessary dependencies.
- Eliminate frontend JS build step completely: (remove dep: NodeJS, npx, tailwind, postcss, autoprefixer) - Declutter and cleanup index.html (8.49 KB to 3.4 KB) = ~60% savings. - Replace tailwind with custom CSS (10.64 KB to 1.96 KB) = ~81% savings. - Remove Google font (~100 KB) as there is very little text on the page. - Refactor and cleanup main.js and remove tailwind styling logic. (2.82 KB to 1.12 KB) = ~60% savings. - Net static asset reduction = 21.95 KB to 6.48 KB = ~70% savings apart from the 100+ KB elimination of Google fonts.
- Loading branch information
Showing
5 changed files
with
335 additions
and
1,433 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,154 +1,90 @@ | ||
const $ = document.querySelector.bind(document); | ||
const $new = document.createElement.bind(document); | ||
const apiURL = "/api/lookup/"; | ||
const isMobile = window.matchMedia("only screen and (max-width: 760px)").matches; | ||
|
||
function handleNSChange() { | ||
if ($('select[name=ns]').value == "custom") { | ||
$('div[id=custom_ns]').classList.remove("hidden"); | ||
$('div[id=ns]').classList.add("hidden"); | ||
} else { | ||
$('div[id=custom_ns]').classList.add("hidden"); | ||
$('div[id=ns]').classList.remove("hidden"); | ||
$('input[name=ns]').placeholder = $('select[name=ns]').value; | ||
} | ||
} | ||
|
||
|
||
// Source: https://stackoverflow.com/a/1026087. | ||
function capitalizeFirstLetter(string) { | ||
return string.charAt(0).toUpperCase() + string.slice(1); | ||
} | ||
|
||
window.addEventListener('DOMContentLoaded', (event) => { | ||
handleNSChange(); | ||
}); | ||
const $show = (el) => { | ||
el.classList.remove('hidden'); | ||
}; | ||
const $hide = (el) => { | ||
el.classList.add('hidden'); | ||
}; | ||
|
||
const apiURL = '/api/lookup/'; | ||
|
||
(function () { | ||
const fields = ['name', 'address', 'type', 'ttl', 'rtt', 'nameserver']; | ||
const fields = ['name', 'address', 'type', 'ttl', 'rtt']; | ||
|
||
// createRow creates a table row with the given cell values. | ||
function createRow(item) { | ||
const tr = $new('tr'); | ||
fields.forEach((f) => { | ||
const td = $new('td'); | ||
td.classList.add("px-6", "py-4", "whitespace-nowrap", "text-sm"); | ||
if (f == "ttl" || f == "rtt" || f == "nameserver") { | ||
td.classList.add("text-gray-500"); | ||
} else { | ||
td.classList.add("text-gray-900"); | ||
} | ||
if (f == "name") { | ||
td.classList.add("font-semibold"); | ||
} | ||
if (f == "type") { | ||
td.innerHTML = '<span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-100 text-green-800">' + item[f] + '</span>'; | ||
} else { | ||
td.innerText = item[f]; | ||
} | ||
td.innerText = item[f]; | ||
td.classList.add(f); | ||
tr.appendChild(td); | ||
}); | ||
return tr; | ||
} | ||
|
||
const handleSubmit = async () => { | ||
const tbody = $('#table tbody'), | ||
tbl = $('#table'); | ||
tbody.innerHTML = ''; | ||
$hide(tbl); | ||
|
||
// `createList` creates a table row with the given cell values. | ||
function createList(item) { | ||
const ul = $new('ul'); | ||
ul.classList.add("m-4", "block", "bg-indigo-100"); | ||
fields.forEach((f) => { | ||
const li = $new('li'); | ||
const span = $new('span'); | ||
span.classList.add("p-2", "text-gray-500", "font-semibold"); | ||
span.innerText = capitalizeFirstLetter(f) + ': ' + item[f] | ||
li.appendChild(span); | ||
ul.appendChild(li); | ||
}); | ||
return ul; | ||
} | ||
|
||
function prepareNSAddr(ns) { | ||
switch (ns) { | ||
// If it's a custom nameserver, get the value from the user's input. | ||
case "custom": | ||
return $('input[name=custom_ns]').value.trim() | ||
// Else get it from the select dropdown field. | ||
default: | ||
return $('select[name=ns]').value.trim() | ||
} | ||
} | ||
|
||
const postForm = body => { | ||
return fetch(apiURL, { | ||
method: 'POST', | ||
headers: { | ||
'Content-Type': 'application/json' | ||
}, | ||
body | ||
}); | ||
}; | ||
|
||
const handleSubmit = async (e) => { | ||
e.preventDefault(); | ||
|
||
const tbl = $('table tbody'); | ||
const list = $('div[id=mobile-answers-sec]'); | ||
tbl.innerHTML = ''; | ||
list.innerHTML = ''; | ||
|
||
$('p[id=empty-name-sec]').classList.add("hidden"); | ||
const errSec = $('div[id=api-error-sec]'); | ||
errSec.classList.add("hidden"); | ||
|
||
const q = $('input[name=q]').value.trim(), typ = $('select[name=type]').value; | ||
const ns = $('select[name=ns]').value; | ||
|
||
if (!q) { | ||
$('p[id=empty-name-sec]').classList.remove("hidden"); | ||
throw ('Invalid query name.'); | ||
} | ||
const q = $('input[name=q]').value.trim(), | ||
typ = $('select[name=type]').value, | ||
addr = $('input[name=address]').value.trim(); | ||
|
||
if (!q || !typ || !ns) { | ||
throw ('Invalid or empty query params.'); | ||
} | ||
// Post to the API. | ||
const req = await fetch(apiURL, { | ||
method: 'POST', | ||
headers: { 'Content-Type': 'application/json' }, | ||
body: JSON.stringify({ query: [q,], type: [typ,], nameservers: [addr,] }) | ||
}); | ||
|
||
const nsAddr = prepareNSAddr(ns); | ||
const body = JSON.stringify({ query: [q,], type: [typ,], nameservers: [nsAddr,] }); | ||
const res = await req.json(); | ||
|
||
const response = await postForm(body); | ||
const res = await response.json(); | ||
if (res.status != "success") { | ||
// get error message from body or default to response statusText | ||
if (res.status != 'success') { | ||
const error = (res && res.message) || response.statusText; | ||
errSec.classList.remove("hidden"); | ||
errSec.innerHTML = '<p class="text-xl text-red-500">' + error + '</p>' | ||
throw (error); | ||
throw(error); | ||
return; | ||
} | ||
|
||
if (res.data[0].answers == null) { | ||
const errSec = $('div[id=api-error-sec]'); | ||
errSec.classList.remove("hidden"); | ||
errSec.innerHTML = '<p class="text-xl text-red-500">' + 'No records found!' + '</p>' | ||
return null; | ||
throw('No records found.'); | ||
return; | ||
} | ||
|
||
$('div[id=answer_sec]').classList.remove("hidden"); | ||
res.data[0].answers.forEach((item) => { | ||
tbody.appendChild(createRow(item)); | ||
}); | ||
|
||
if (isMobile === true) { | ||
list.classList.remove("hidden"); | ||
res.data[0].answers.forEach((item) => { | ||
console.log("appending", item) | ||
list.appendChild(createList(item)); | ||
}); | ||
$show(tbl); | ||
}; | ||
|
||
} else { | ||
res.data[0].answers.forEach((item) => { | ||
tbl.appendChild(createRow(item)); | ||
}); | ||
} | ||
// Capture the form submit. | ||
$('#form').onsubmit = async (e) => { | ||
e.preventDefault(); | ||
|
||
const msg = $('#message'); | ||
$hide(msg); | ||
|
||
try { | ||
await handleSubmit(); | ||
} catch(e) { | ||
msg.innerText = e.toString(); | ||
$show(msg); | ||
throw e; | ||
} | ||
}; | ||
|
||
document.querySelector('form').addEventListener('submit', handleSubmit); | ||
// Change the address on ns change. | ||
const ns = $("#ns"), addr = $("#address"); | ||
addr.value = ns.value; | ||
|
||
ns.onchange = (e) => { | ||
addr.value = e.target.value; | ||
if(addr.value === "") { | ||
addr.focus(); | ||
} | ||
}; | ||
})(); |
Oops, something went wrong.