From bce774d48c1a2eb3384b4b89b019af1f2a4fe770 Mon Sep 17 00:00:00 2001 From: Arthur Lu Date: Tue, 14 Nov 2023 00:09:41 +0000 Subject: [PATCH] fix bugs in network config change, generalize dialog layout, add form validation callback, add password change form --- account.html | 15 +++------ scripts/account.js | 33 ++++++++++++++++++++ scripts/config.js | 76 +++++++++++++++++++++++++++++++++------------- scripts/dialog.js | 35 +++++++++++++++++---- scripts/index.js | 58 ++++++++++++++++++----------------- 5 files changed, 151 insertions(+), 66 deletions(-) diff --git a/account.html b/account.html index ba7ce45..4a2f349 100644 --- a/account.html +++ b/account.html @@ -64,17 +64,10 @@

Nodes:

-

Password

-
-
- - - - - - -
-
+
+

Password

+ +

Cluster Resources

diff --git a/scripts/account.js b/scripts/account.js index afe31b5..5ed19d8 100644 --- a/scripts/account.js +++ b/scripts/account.js @@ -1,3 +1,4 @@ +import { dialog } from "./dialog.js"; import { requestAPI, goToPage, getCookie, setTitleAndHeader } from "./utils.js"; window.addEventListener("DOMContentLoaded", init); @@ -42,6 +43,8 @@ async function init () { document.querySelector("#nodes").innerText = `Nodes: ${nodes.toString()}`; populateResources("#resource-container", meta, resources); + + document.querySelector("#change-password").addEventListener("click", handlePasswordChangeForm); } function populateResources (containerID, meta, resources) { @@ -117,3 +120,33 @@ function parseNumber (value, unitData) { return `${value} ${unit}`; } } + +function handlePasswordChangeForm () { + const body = ` +
+ + + + +
+

+ `; + dialog("Change Password", body, async (result, form) => { + if (result === "confirm") { + const result = await requestAPI("/auth/password", "POST", {password: form.get("new-password")}); + if (result.status !== 200) { + alert(result.error); + } + } + }, (dialog, form) => { + const pass = form.get("new-password"); + const conf = form.get("confirm-password"); + if (pass !== conf) { + dialog.querySelector("#error-message").innerText = "Passwords must match"; + return false; + } + else { + return true; + } + }); +} diff --git a/scripts/config.js b/scripts/config.js index e557a84..5b5fdf7 100644 --- a/scripts/config.js +++ b/scripts/config.js @@ -233,7 +233,7 @@ function addDiskLine (fieldset, busPrefix, busName, device, diskDetails) { async function handleDiskDetach () { const disk = this.dataset.disk; const header = `Detach ${disk}`; - const body = `

Are you sure you want to detach disk

${disk}

`; + const body = `

Are you sure you want to detach disk ${disk}

`; dialog(header, body, async (result, form) => { if (result === "confirm") { document.querySelector(`img[data-disk="${disk}"]`).src = "images/status/loading.svg"; @@ -250,7 +250,12 @@ async function handleDiskDetach () { async function handleDiskAttach () { const header = `Attach ${this.dataset.disk}`; - const body = ``; + const body = ` +
+ + +
+ `; dialog(header, body, async (result, form) => { if (result === "confirm") { @@ -274,7 +279,12 @@ async function handleDiskAttach () { async function handleDiskResize () { const header = `Resize ${this.dataset.disk}`; - const body = ""; + const body = ` +
+ + +
+ `; dialog(header, body, async (result, form) => { if (result === "confirm") { @@ -310,8 +320,10 @@ async function handleDiskMove () { const select = ``; const body = ` - ${select} - +
+ ${select} + +
`; dialog(header, body, async (result, form) => { @@ -337,7 +349,7 @@ async function handleDiskMove () { async function handleDiskDelete () { const disk = this.dataset.disk; const header = `Delete ${disk}`; - const body = `

Are you sure you want to delete disk

${disk}

`; + const body = `

Are you sure you want to delete disk${disk}

`; dialog(header, body, async (result, form) => { if (result === "confirm") { document.querySelector(`img[data-disk="${disk}"]`).src = "images/status/loading.svg"; @@ -367,9 +379,11 @@ async function handleDiskAdd () { const select = ``; const body = ` - - ${select} - +
+ + ${select} + +
`; dialog(header, body, async (result, form) => { @@ -407,9 +421,11 @@ async function handleCDAdd () { const storageSelect = ``; const body = ` - - ${storageSelect} - +
+ + ${storageSelect} + +
`; const d = dialog(header, body, async (result, form) => { @@ -509,7 +525,11 @@ async function handleNetworkConfig () { const netID = this.dataset.network; const netDetails = this.dataset.values; const header = `Edit net${netID}`; - const body = ""; + const body = ` +
+ +
+ `; const d = dialog(header, body, async (result, form) => { if (result === "confirm") { @@ -523,7 +543,8 @@ async function handleNetworkConfig () { } await getConfig(); populateNetworks(); - updateBootLine(`boot-net${netID}`, { id: `net${netID}`, prefix: "net", value: config.data[`net${netID}`] }); + const id = `net${netID}`; + updateBootLine(`boot-net${netID}`, { id, prefix: "net", value: id, detail: config.data[`net${netID}`] }); } }); @@ -551,10 +572,15 @@ async function handleNetworkDelete () { async function handleNetworkAdd () { const header = "Create Network Interface"; - let body = ""; + let body = ` +
+ + + `; if (type === "lxc") { body += ""; } + body += "
"; dialog(header, body, async (result, form) => { if (result === "confirm") { @@ -648,7 +674,11 @@ async function handleDeviceConfig () { const deviceDetails = this.dataset.values; const deviceName = this.dataset.name; const header = `Edit Expansion Card ${deviceID}`; - const body = ""; + const body = ` +
+ +
+ `; const d = dialog(header, body, async (result, form) => { if (result === "confirm") { @@ -694,7 +724,11 @@ async function handleDeviceDelete () { async function handleDeviceAdd () { const header = "Add Expansion Card"; - const body = ""; + const body = ` +
+ +
+ `; const d = dialog(header, body, async (result, form) => { if (result === "confirm") { @@ -798,11 +832,11 @@ function updateBootLine (id, newData) { const enabled = document.querySelector("#enabled"); const disabled = document.querySelector("#disabled"); let element = null; - if (enabled.getItemByID(id)) { - element = enabled.getItemByID(id); + if (enabled.querySelector(`#${id}`)) { + element = enabled.querySelector(`#${id}`); } - if (disabled.getItemByID(id)) { - element = disabled.getItemByID(id); + if (disabled.querySelector(`#${id}`)) { + element = disabled.querySelector(`#${id}`); } if (element) { const container = element.container; diff --git a/scripts/dialog.js b/scripts/dialog.js index fa9e28f..af1540e 100644 --- a/scripts/dialog.js +++ b/scripts/dialog.js @@ -1,20 +1,43 @@ -export function dialog (header, body, callback = async (result, form) => { }) { +export function dialog (header, body, onclose = async (result, form) => { }, validate = async (dialog, form) => { + return true; +}) { const dialog = document.createElement("dialog"); dialog.innerHTML = `

-
+
- - + +
`; dialog.className = "w3-container w3-card w3-border-0"; dialog.querySelector("#prompt").innerText = header; - dialog.querySelector("form").innerHTML = body; + dialog.querySelector("#body").innerHTML = body; dialog.addEventListener("close", async () => { - await callback(dialog.returnValue, new FormData(dialog.querySelector("form"))); + const formElem = dialog.querySelector("form"); + let formData = null; + if (formElem) { + formData = new FormData(formElem); + } + await onclose(dialog.returnValue, formData); dialog.parentElement.removeChild(dialog); }); + dialog.querySelector("#confirm").addEventListener("click", async (e) => { + e.preventDefault(); + let valid = true; + const formElem = dialog.querySelector("form"); + if (formElem) { + const form = new FormData(formElem); + valid = await validate(dialog, form); + } + if (valid) { + dialog.close(e.target.value); + } + }); + dialog.querySelector("#cancel").addEventListener("click", async (e) => { + e.preventDefault(); + dialog.close(e.target.value); + }); document.body.append(dialog); dialog.showModal(); return dialog; diff --git a/scripts/index.js b/scripts/index.js index 2820412..0e648be 100644 --- a/scripts/index.js +++ b/scripts/index.js @@ -78,34 +78,36 @@ async function handleInstanceAdd () { const header = "Create New Instance"; const body = ` - - - - - - - - - - - - -

Container Options

- - - - - - - - - - - - +
+ + + + + + + + + + + + +

Container Options

+ + + + + + + + + + + + +
`; const d = dialog(header, body, async (result, form) => {