www.spaceplanner.app

Web client to the spaceplanner API
git clone git://jacobedwards.org/www.spaceplanner.app
Log | Files | Refs

main.js (5933B)


      1 import * as api from "/lib/api.js"
      2 import * as etc from "/lib/etc.js"
      3 import * as ui from "/lib/ui.js"
      4 
      5 etc.handle_wrap(init)
      6 
      7 function init() {
      8 	etc.authorize()
      9 	etc.bar()
     10 	main()
     11 }
     12 
     13 function main() {
     14 	update_info("Username", localStorage.getItem("username"))
     15 
     16 	let errfunc = function(err) { etc.error("Unable to get settings: " + err, document.querySelector("#settings")) }
     17 	api.fetch("GET", "settings")
     18 		.then(function(params) {
     19 			api.fetch("GET", "users/:user/settings")
     20 				.then(function(current) {
     21 					show_settings(current, params)
     22 				})
     23 		})
     24 		.catch(errfunc)
     25 
     26 	let h = document.body.appendChild(
     27 		document.createElement("h2")
     28 	)
     29 	h.appendChild(document.createTextNode("Delete Account"))
     30 	let del = delete_form()
     31 	del.onsubmit = delete_user
     32 	document.body.append(del)
     33 }
     34 
     35 function delete_form() {
     36 	let form = document.createElement("form")
     37 	form.id = "delete_user_form"
     38 
     39 	form.appendChild(ui.warning("This action cannot be undone."))
     40 
     41 	let label = document.createElement("label")
     42 	label.setAttribute("for", "delete_user_confirm")
     43 	label.appendChild(document.createTextNode("Confirm: "))
     44 	form.append(label)
     45 
     46 	let check = document.createElement("input")
     47 	check.id = "delete_user_confirm"
     48 	check.type = "checkbox"
     49 	check.setAttribute("required", true)
     50 	form.append(check)
     51 
     52 	form.appendChild(document.createTextNode(" "))
     53 
     54 	let submit = document.createElement("input")
     55 	submit.type = "submit"
     56 	submit.value = "Delete Account"
     57 	form.append(submit)
     58 
     59 	return form
     60 }
     61 
     62 function delete_user() {
     63 	api.fetch("DELETE", "users/:user")
     64 		.then(function() {
     65 			api.update_token(null)
     66 			document.location.href = "/"
     67 		})
     68 		.catch(function(err) { etc.error("Unable to delete user: " + err, document.getElementById("#delete_form")) })
     69 	return false
     70 }
     71 
     72 function show_settings(current, params) {
     73 	let form = document.createElement("form")
     74 	form.id = "settings"
     75 	let list = document.createElement("ul")
     76 	form.append(list)
     77 	for (name in params) {
     78 		let id = name + "_setting"
     79 		let item = document.createElement("li")
     80 
     81 		let label = document.createElement("label")
     82 		label.setAttribute("for", id)
     83 		
     84 		label.appendChild(document.createTextNode(ui.prettyName(name, { title: false }) + " "))
     85 		item.append(label)
     86 
     87 		let input = create_input(name, params[name], current[name])
     88 		input.id = id
     89 		input.setAttribute("title", params[name].description)
     90 		item.append(input)
     91 
     92 		list.append(item)
     93 	}
     94 
     95 	let submit = document.createElement("input")
     96 	submit.value = "Update"
     97 	submit.type = "submit"
     98 	form.append(submit)
     99 
    100 	form.addEventListener("submit", function(event) {
    101 		event.preventDefault()
    102 		update_settings(current, params)
    103 	})
    104 
    105 	let current_form = document.querySelector("#settings")
    106 	current_form.replaceWith(form)
    107 
    108 	update_verified_email()
    109 }
    110 
    111 function update_settings(current, params) {
    112 	let settings = Array.from(document.querySelectorAll("form#settings > ul > li > input"))
    113 	let patch = []
    114 	for (let i in settings) {
    115 		let name = settings[i].name
    116 		let oldvalue = current[name]
    117 		let newvalue
    118 		if (settings[i].getAttribute("type") == "checkbox") {
    119 			newvalue = settings[i].checked
    120 		} else {
    121 			newvalue = settings[i].value
    122 		}
    123 
    124 		if (params.default && newvalue == params.default) {
    125 			if (oldvalue != null) {
    126 				patch.push({ op: "remove", path: name })
    127 			}
    128 		} else if (newvalue != oldvalue) {
    129 			if (name === "email") {
    130 				update_verified_email()
    131 			}
    132 			patch.push({ op: "add", path: name, value: newvalue })
    133 		}
    134 	}
    135 
    136 	if (patch.length == 0) {
    137 		return
    138 	}
    139 	api.fetch("PATCH", "users/:user/settings", patch)
    140 		.then(function(updated) {
    141 			for (let k in updated) {
    142 				current[k] = updated[k]
    143 			}
    144 			// Alert in a less annoying way
    145 			alert("Settings successfully updated")
    146 		})
    147 		.catch(function(err) { etc.error("Unable to update settings: " + err) })
    148 }
    149 
    150 function update_verified_email() {
    151 	let setting_form = document.querySelector('input[name="email"]')
    152 	if (!setting_form) {
    153 		throw new Error("Expected email setting")
    154 	}
    155 
    156 	api.verifiedEmail()
    157 		.then(function(verified) {
    158 			update_info("Email", verified)
    159 			let old_warning = document.getElementById("unverified_email_warning")
    160 			if (verified == setting_form.value) {
    161 				if (old_warning != null) {
    162 					old_warning.remove()
    163 				}
    164 			} else if (verified == null || verified != setting_form.value) {
    165 				let content = document.createElement("p")
    166 				content.appendChild(document.createTextNode("This email is not verified. Please verify it "))
    167 				let a = content.appendChild(document.createElement("a"))
    168 				a.href = "./verify-email"
    169 				a.appendChild(document.createTextNode("here."))
    170 
    171 				let warning = ui.warning(content)
    172 				warning.id = "unverified_email_warning"
    173 				warning.classList.add("small")
    174 			
    175 				if (old_warning != null) {
    176 					old_warning.replaceWith(warning)
    177 				} else {
    178 					setting_form.after(warning)
    179 				}
    180 			}
    181 		})
    182 }
    183 
    184 function create_input(name, setting, current_value) {
    185 	let input = document.createElement("input")
    186 	if (setting.type == "string") {
    187 		input.type = name === "email" ? "email" : "text"
    188 	} else if (setting.type == "bool") {
    189 		input.type = "checkbox"
    190 		if (current_value) {
    191 			input.setAttribute("checked", "true")
    192 		}
    193 	} else {
    194 		throw new Error("Unexpected setting type")
    195 	}
    196 
    197 	input.name = name
    198 	if (current_value) {
    199 		input.value = current_value
    200 	}
    201 
    202 	return input
    203 }
    204 
    205 function update_info(key, value) {
    206 	let dl = document.getElementById("userinfo")
    207 
    208 	if (value == null) {
    209 		return
    210 	}
    211 
    212 	let v = get_info_element(key)
    213 	if (v != undefined) {
    214 		v.textContent = value
    215 		return
    216 	}
    217 
    218 	let k = dl.appendChild(document.createElement("dt"))
    219 	k.appendChild(document.createTextNode(key))
    220 	v = dl.appendChild(document.createElement("dd"))
    221 	v.appendChild(document.createTextNode(value))
    222 }
    223 
    224 function get_info_element(key) {
    225 	let dl = document.getElementById("userinfo")
    226 
    227 	let k
    228 	let keys = Array.from(dl.querySelectorAll("dt"))
    229 	for (let i in keys) {
    230 		if (keys[i].textContent == key) {
    231 			return keys[i].nextElementSibling
    232 		}
    233 	}
    234 
    235 	return undefined
    236 }