commit 4e3f704e5015758cbe62ce017fe32fe538dfd4ea
parent 564ce65269c7c8c084335be078076d1ddbdd3b02
Author: Jacob R. Edwards <jacob@jacobedwards.org>
Date: Fri, 30 Aug 2024 18:25:51 -0700
Update settings page
There were a lot of improvements and changes, but the core differences
are listing the user's name and verified email, and linking to email
verification page when email is not verified.
Diffstat:
2 files changed, 130 insertions(+), 26 deletions(-)
diff --git a/files/settings/index.html b/files/settings/index.html
@@ -5,7 +5,13 @@
<script type="module" src="./main.js"></script>
</head>
<html>
- <h1>Settings</h1>
+ <h1>Profile</h1>
+
+ <dl id="userinfo"></dl>
+
+ <a href="./billing/">Manage billing</a>
+
+ <h2>Settings</h2>
<form id="settings"></form>
</html>
diff --git a/files/settings/main.js b/files/settings/main.js
@@ -1,5 +1,6 @@
import * as api from "/lib/api.js"
import * as etc from "/lib/etc.js"
+import * as ui from "/lib/ui.js"
function init() {
etc.authorize()
@@ -8,6 +9,8 @@ function init() {
}
function main() {
+ update_info("Username", localStorage.getItem("username"))
+
let errfunc = function(err) { etc.error("Unable to get settings: " + err, document.querySelector("#settings")) }
api.fetch("GET", "settings")
.then(function(params) {
@@ -18,9 +21,10 @@ function main() {
})
.catch(errfunc)
- let profile = document.createElement("h2")
- profile.appendChild(document.createTextNode("Profile"))
- document.body.append(profile)
+ let h = document.body.appendChild(
+ document.createElement("h2")
+ )
+ h.appendChild(document.createTextNode("Delete Account"))
let del = delete_form()
del.onsubmit = delete_user
document.body.append(del)
@@ -30,9 +34,11 @@ function delete_form() {
let form = document.createElement("form")
form.id = "delete_user_form"
+ form.appendChild(ui.warning("This action cannot be undone."))
+
let label = document.createElement("label")
label.setAttribute("for", "delete_user_confirm")
- label.appendChild(document.createTextNode("Confirm "))
+ label.appendChild(document.createTextNode("Confirm: "))
form.append(label)
let check = document.createElement("input")
@@ -41,13 +47,13 @@ function delete_form() {
check.setAttribute("required", true)
form.append(check)
+ form.appendChild(document.createTextNode(" "))
+
let submit = document.createElement("input")
submit.type = "submit"
- submit.value = "Delete User"
+ submit.value = "Delete Account"
form.append(submit)
- form.appendChild(document.createTextNode("This action cannot be undone."))
-
return form
}
@@ -73,21 +79,14 @@ function show_settings(current, params) {
let label = document.createElement("label")
label.setAttribute("for", id)
- label.appendChild(document.createTextNode(name[0].toUpperCase() + name.substring(1) + " "))
+ label.appendChild(document.createTextNode(ui.prettyName(name, { title: false }) + " "))
item.append(label)
let input = create_input(name, params[name], current[name])
input.id = id
+ input.setAttribute("title", params[name].description)
item.append(input)
- /*
- *desc = document.createElement("label")
- *desc.setAttribute("for", id)
- *desc.append(document.createElement("br"))
- *desc.appendChild(document.createTextNode(params[name].description))
- *item.append(desc)
- */
-
list.append(item)
}
@@ -96,34 +95,104 @@ function show_settings(current, params) {
submit.type = "submit"
form.append(submit)
- form.onsubmit = function () { return update_settings(current, params) }
+ form.addEventListener("submit", function(event) {
+ event.preventDefault()
+ update_settings(current, params)
+ })
let current_form = document.querySelector("#settings")
current_form.replaceWith(form)
+
+ update_verified_email()
}
function update_settings(current, params) {
let settings = Array.from(document.querySelectorAll("form#settings > ul > li > input"))
let patch = []
- for (let name in settings) {
- let newvalue = settings[name].value
- if (params.default && newvalue == params.default)
- continue
+ for (let i in settings) {
+ let name = settings[i].name
let oldvalue = current[name]
- if (oldvalue && newvalue == oldvalue)
- continue
- patch.push({ op: "add", path: settings[name].name, value: newvalue })
+ let newvalue
+ if (settings[i].getAttribute("type") == "checkbox") {
+ newvalue = settings[i].checked
+ } else {
+ newvalue = settings[i].value
+ }
+
+ if (params.default && newvalue == params.default) {
+ if (oldvalue != null) {
+ patch.push({ op: "remove", path: name })
+ }
+ } else if (newvalue != oldvalue) {
+ if (name === "email") {
+ update_verified_email()
+ }
+ patch.push({ op: "add", path: name, value: newvalue })
+ }
}
+ if (patch.length == 0) {
+ return
+ }
api.fetch("PATCH", "users/" + localStorage.getItem("username") + "/settings", patch)
+ .then(function(updated) {
+ for (let k in updated) {
+ current[k] = updated[k]
+ }
+ // Alert in a less annoying way
+ alert("Settings successfully updated")
+ })
.catch(function(err) { etc.error("Unable to update settings: " + err) })
- return false
+}
+
+function update_verified_email() {
+ let setting_form = document.querySelector('input[name="email"]')
+ if (!setting_form) {
+ throw new Error("Expected email setting")
+ }
+
+ api.fetch("GET", "users/" + localStorage.getItem("username") + "/email/verified")
+ .then(function(verified) {
+ update_info("Email", verified)
+ let old_warning = document.getElementById("unverified_email_warning")
+ if (verified == setting_form.value) {
+ if (old_warning != null) {
+ old_warning.remove()
+ }
+ } else if (verified != setting_form.value) {
+ let content
+ if (verified == null)
+ content = ui.warning("This email is not verified.")
+ else {
+ content = document.createElement("p")
+ content.appendChild(document.createTextNode("This email is not verified. Please verify it "))
+ let a = content.appendChild(document.createElement("a"))
+ a.href = "./verify-email"
+ a.appendChild(document.createTextNode("here."))
+ }
+
+ let warning = ui.warning(content)
+ warning.id = "unverified_email_warning"
+ warning.classList.add("small")
+
+ if (old_warning != null) {
+ old_warning.replaceWith(warning)
+ } else {
+ setting_form.after(warning)
+ }
+ }
+ })
}
function create_input(name, setting, current_value) {
let input = document.createElement("input")
if (setting.type == "string") {
input.type = "text"
+ } else if (setting.type == "bool") {
+ input.type = "checkbox"
+ if (current_value) {
+ input.setAttribute("checked", "true")
+ }
} else {
throw new Error("Unexpected setting type")
}
@@ -136,4 +205,33 @@ function create_input(name, setting, current_value) {
return input
}
+function update_info(key, value) {
+ let dl = document.getElementById("userinfo")
+
+ let v = get_info_element(key)
+ if (v != undefined) {
+ v.textContent = value
+ return
+ }
+
+ let k = dl.appendChild(document.createElement("dt"))
+ k.appendChild(document.createTextNode(key))
+ v = dl.appendChild(document.createElement("dd"))
+ v.appendChild(document.createTextNode(value))
+}
+
+function get_info_element(key) {
+ let dl = document.getElementById("userinfo")
+
+ let k
+ let keys = Array.from(dl.querySelectorAll("dt"))
+ for (let i in keys) {
+ if (keys[i].textContent == key) {
+ return keys[i].nextElementSibling
+ }
+ }
+
+ return undefined
+}
+
window.onload = etc.handle_wrap(init)