2 let breadcrumbs = await _require('/_lib/breadcrumbs.jst')
3 let fa_envelope = await env.site.get_min_svg('/_svg/fa_envelope.svg')
4 let get_placeholder = await _require('/_lib/get_placeholder.jst')
5 let get_session = await _require('/_lib/get_session.jst')
6 let icon_cross = await env.site.get_min_svg('/_svg/icon_cross.svg')
7 let icon_tick = await env.site.get_min_svg('/_svg/icon_tick.svg')
8 let navbar = await _require('/_lib/navbar.jst')
10 // preload placeholder
11 let transaction = await env.site.database.Transaction()
14 let root = await transaction.get({})
15 let session = await get_session(env, root)
16 placeholder = await get_placeholder(env, session)
17 await transaction.commit()
20 transaction.rollback()
24 // preload URL details if any
26 Object.prototype.hasOwnProperty.call(
30 decodeURIComponent(env.parsed_url.query.email) :
39 await breadcrumbs(env, _out)
41 p {'To reset your password, please enter new details below and we will send you a password reset link.'}
47 label.form-label(for="email") {'Email *'}
48 input.form-control#email(type="email" value=email placeholder=placeholder.email required="required" maxlength=256) {}
49 div.invalid-feedback {'Please enter your account\'s email address.'}
54 label.form-label(for="new-password") {'New password *'}
55 input.form-control#new-password(type="password" placeholder="Choose" required="required" minlength=8 maxlength=256) {}
56 div.invalid-feedback {'Please choose a secure password of at least 8 characters.'}
63 button.btn.btn-success#password-reset(type="button") {
64 div.icon24-outer.mr-2#icon {
65 div.icon24-inner {_out.push(fa_envelope)}
67 div.icon24-outer.mr-2#tick(hidden) {
68 div.icon24-inner {_out.push(icon_tick)}
70 div.icon24-outer.mr-2#cross(hidden) {
71 div.icon24-inner {_out.push(icon_cross)}
73 div.icon24-outer.mr-2#spinner(hidden) {
75 div.spinner-border.spinner-border-sm(role="status") {}
81 button.btn.btn-success#password-reset(type="button" disabled) {
82 div.icon24-outer.mr-2#icon {
83 div.icon24-inner {_out.push(fa_envelope)}
85 div.icon24-outer.mr-2#tick(hidden) {
86 div.icon24-inner {_out.push(icon_tick)}
88 div.icon24-outer.mr-2#cross(hidden) {
89 div.icon24-inner {_out.push(icon_cross)}
91 div.icon24-outer.mr-2#spinner(hidden) {
93 div.spinner-border.spinner-border-sm(role="status") {}
99 p.'mt-3'.mb-0#message(hidden) {}
101 p.text-muted.mt-3 {'* These fields are required.'}
105 //script(src="/js/utils.js") {}
108 document.addEventListener(
111 let id_cross = document.getElementById('cross')
112 let id_email = document.getElementById('email')
113 let id_form = document.getElementById('form')
114 let id_icon = document.getElementById('icon')
115 let id_message = document.getElementById('message')
116 let id_new_password = document.getElementById('new-password')
117 let id_password_reset = document.getElementById('password-reset')
118 let id_spinner = document.getElementById('spinner')
119 let id_tick = document.getElementById('tick')
122 id_password_reset.disabled =
123 id_email.value.length === 0 &&
124 id_new_password.value.length === 0
125 id_icon.hidden = false
126 id_tick.hidden = true
127 id_cross.hidden = true
128 id_spinner.hidden = true
129 id_message.hidden = true
132 id_email.addEventListener('input', edited)
133 id_new_password.addEventListener('input', edited)
135 id_password_reset.addEventListener(
138 id_icon.hidden = false
139 id_tick.hidden = true
140 id_cross.hidden = true
141 id_spinner.hidden = true
142 // the below causes an ugly flicker, so just keep the message
143 //id_message.hidden = true
145 if (!id_form.checkValidity()) {
146 id_form.classList.add('was-validated');
148 id_icon.hidden = true
149 id_cross.hidden = false
152 id_form.classList.remove('was-validated');
154 let email = id_email.value.slice(0, 256).toLowerCase()
155 let new_password = id_new_password.value.slice(0, 256)
157 id_icon.hidden = true
158 id_spinner.hidden = false
161 '/api/account/password_reset.json',
167 let problem = Problem.from(error)
169 id_cross.hidden = false
170 id_spinner.hidden = true
172 id_message.textContent = problem.detail
173 //id_message.classList.remove('text-success')
174 id_message.classList.add('text-danger')
175 id_message.hidden = false
178 id_tick.hidden = false
179 id_spinner.hidden = true
180 id_message.textContent = `Password reset link has been sent to "${email}". Please check your email for next steps.`
181 //id_message.classList.add('text-success')
182 id_message.classList.remove('text-danger')
183 id_message.hidden = false