return async env => {
let breadcrumbs = await _require('/_lib/breadcrumbs.jst')
+ let fa_user_check = await env.site.get_min_svg('/_svg/fa_user-check.svg')
+ let get_placeholder = await _require('/_lib/get_placeholder.jst')
+ let get_session = await _require('/_lib/get_session.jst')
let icon_cross = await env.site.get_min_svg('/_svg/icon_cross.svg')
let icon_tick = await env.site.get_min_svg('/_svg/icon_tick.svg')
let navbar = await _require('/_lib/navbar.jst')
- // preload draft details if any
- let details = {}
- if (Object.prototype.hasOwnProperty.call(env.parsed_url.query, 'email'))
- details.email = decodeURIComponent(env.parsed_url.query.email)
- if (
- Object.prototype.hasOwnProperty.call(
+ // preload placeholder
+ let transaction = await env.site.database.Transaction()
+ let placeholder
+ try {
+ let root = await transaction.get({})
+ let session = await get_session(env, root)
+ placeholder = await get_placeholder(env, session)
+ transaction.commit()
+ }
+ catch (error) {
+ transaction.rollback()
+ throw error
+ }
+
+ // preload URL details if any
+ let email =
+ Object.prototype.hasOwnProperty.call(
+ env.parsed_url.query,
+ 'email'
+ ) ?
+ decodeURIComponent(env.parsed_url.query.email) :
+ ''
+ let link_code =
+ Object.prototype.hasOwnProperty.call(
env.parsed_url.query,
'link_code'
- )
- )
- details.link_code =
- decodeURIComponent(env.parsed_url.query.link_code)
- console.log('details', JSON.stringify(details))
+ ) ?
+ decodeURIComponent(env.parsed_url.query.link_code) :
+ ''
- await navbar(
+ await navbar(
env,
// head
async _out => {},
p {'You will need to verify your email address via an emailed link before you can sign in to your account.'}
- div.accordion#accordion.mb-5(role="tablist" aria-multiselectable="true") {
- div.card#step-1 {
- div.card-header#step-1-heading(role="tab") {
- span#step-1-tick(style="display: none;") {
- span.icon-color.pr-3 {_out.push(icon_tick)}
- }
- span#step-1-cross(style="display: none;") {
- span.icon-color.pr-3 {_out.push(icon_cross)}
+ form#form {
+ div.row {
+ div.col-md-6 {
+ div.form-group {
+ label.form-label(for="email") {'Email *'}
+ input.form-control#email(type="email" value=email placeholder=placeholder.email required="required" maxlength=256) {}
+ div.invalid-feedback {'Please enter your account\'s email address.'}
}
- //span#step-1-spinner(style="display: none;") {
- // span.icon-color.pr-3 {
- // div.spinner-border(role="status") {
- // span.sr-only {'Loading...'}
- // }
- // }
- //}
- a.h5(data-toggle="collapse" data-parent="#accordion" href="#step-1-collapse" aria-expanded="true" aria-controls="step-1-collapse") {
- 'Link details'
+ }
+ div.col-md-6 {
+ div.form-group {
+ label.form-label(for="link-code") {'Link code *'}
+ input.form-control#link-code(type="text" value=link_code placeholder="00000000000000000000000000000000" required="required" minlength=32 maxlength=32) {}
+ div.invalid-feedback {'Please enter the 32-character code from the link we have emailed to you.'}
}
}
- div#step-1-collapse.collapse.show(role="tabpanel" aria-labelledby="step-1-heading" data-parent="#accordion") {
- div.card-body {
- div.row {
- div.col-md-6 {
- div.form-group {
- label.form-label(for="email") {'Email *'}
- input.form-control#email(type="email" value=details.email || '' placeholder="Account email address" required="required" maxlength=256) {}
- }
- }
- div.col-md-6 {
- div.form-group {
- label.form-label(for="link-code") {'Link code *'}
- input.form-control#link-code(type="text" value=details.link_code || '' placeholder="Type the code from the email link" required="required" minlength=32 maxlength=32) {}
- }
- }
- }
+ }
+ }
- button.btn.btn-success#step-1-continue(type="button") {'Continue'}
- p.'mt-3'.mb-0 {'* These fields are required.'}
+ if (email.length || details.length)
+ button.btn.btn-success#verify-email(type="button") {
+ div.icon24-outer.mr-2#icon {
+ div.icon24-inner {_out.push(fa_user_check)}
+ }
+ div.icon24-outer.mr-2#tick(hidden) {
+ div.icon24-inner {_out.push(icon_tick)}
+ }
+ div.icon24-outer.mr-2#cross(hidden) {
+ div.icon24-inner {_out.push(icon_cross)}
+ }
+ div.icon24-outer.mr-2#spinner(hidden) {
+ div.icon24-inner {
+ div.spinner-border.spinner-border-sm(role="status") {}
}
}
+ 'Verify email'
}
- div.card#step-2 {
- div.card-header#step-2-heading(role="tab") {
- span#step-2-tick(style="display: none;") {
- span.icon-color.pr-3 {_out.push(icon_tick)}
- }
- span#step-2-cross(style="display: none;") {
- span.icon-color.pr-3 {_out.push(icon_cross)}
- }
- span#step-2-spinner(style="display: none;") {
- span.icon-color.pr-3 {
- div.spinner-border(role="status") {
- span.sr-only {'Loading...'}
- }
- }
- }
- a.h5.collapsed(data-toggle="collapse" data-parent="#accordion" href="#step-2-collapse" aria-expanded="false" aria-controls="step-2-collapse") {
- 'Verify email'
- }
+ else
+ button.btn.btn-success#verify-email(type="button" disabled) {
+ div.icon24-outer.mr-2#icon {
+ div.icon24-inner {_out.push(fa_user_check)}
}
- div#step-2-collapse.collapse(role="tabpanel" aria-labelledby="step-2-heading" data-parent="#accordion") {
- div.card-body {
- p#step-2-message {'Please enter link details first.'}
-
- button.btn.btn-outline-secondary#step-2-back(type="button") {'Back'}
- button.btn.btn-outline-secondary.ml-2#step-2-sign-in(type="button") {'Sign in'}
+ div.icon24-outer.mr-2#tick(hidden) {
+ div.icon24-inner {_out.push(icon_tick)}
+ }
+ div.icon24-outer.mr-2#cross(hidden) {
+ div.icon24-inner {_out.push(icon_cross)}
+ }
+ div.icon24-outer.mr-2#spinner(hidden) {
+ div.icon24-inner {
+ div.spinner-border.spinner-border-sm(role="status") {}
}
}
+ 'Verify email'
}
- }
+
+ p.'mt-3'.mb-0#message(hidden) {}
+
+ p.text-muted.mt-3 {'* These fields are required.'}
},
// scripts
async _out => {
//script(src="/js/utils.js") {}
script {
- let step_1 = async () => {
- if (
- !document.getElementById('email').reportValidity() ||
- !document.getElementById('link-code').reportValidity()
- ) {
- $('#step-1-tick').hide()
- $('#step-1-cross').show()
- //$('#step-1-spinner').hide()
- return false
- }
- $('#step-1-tick').show()
- $('#step-1-cross').hide()
- //$('#step-1-spinner').hide()
- return true
- }
-
- let step_2 = async () => {
- $('#step-2-tick').hide()
- $('#step-2-cross').hide()
- $('#step-2-spinner').show()
- document.getElementById('step-1').scrollIntoView()
-
- let email
- try {
- email = document.getElementById('email').value.slice(0, 256).toLowerCase()
- await api_call(
- '/api/account/sign_up/verify_email.json',
- email,
- document.getElementById('link-code').value.slice(0, 32).toLowerCase()
- )
- }
- catch (error) {
- let problem = Problem.from(error)
-
- $('#step-2-tick').hide()
- $('#step-2-cross').show()
- $('#step-2-spinner').hide()
-
- document.getElementById('step-2-message').textContent = problem.detail
- $('#step-2-collapse').collapse('show')
- return false
- }
- $('#step-2-tick').show()
- $('#step-2-cross').hide()
- $('#step-2-spinner').hide()
-
- document.getElementById('step-2-message').textContent = `Your email "${email}" has been verified. You can now sign in.`
- return true
- }
-
document.addEventListener(
'DOMContentLoaded',
() => {
- document.getElementById('step-1-continue').addEventListener(
+ let id_cross = document.getElementById('cross')
+ let id_email = document.getElementById('email')
+ let id_form = document.getElementById('form')
+ let id_icon = document.getElementById('icon')
+ let id_link_code = document.getElementById('link-code')
+ let id_message = document.getElementById('message')
+ let id_spinner = document.getElementById('spinner')
+ let id_tick = document.getElementById('tick')
+ let id_verify_email = document.getElementById('verify-email')
+
+ let edited = () => {
+ id_verify_email.disabled =
+ id_email.value.length === 0 &&
+ id_link_code.value.length === 0
+ id_icon.hidden = false
+ id_tick.hidden = true
+ id_cross.hidden = true
+ id_spinner.hidden = true
+ id_message.hidden = true
+ }
+
+ id_email.addEventListener('input', edited)
+ id_link_code.addEventListener('input', edited)
+
+ id_verify_email.addEventListener(
'click',
async () => {
- if (await step_1() && await step_2())
- $('#step-2-collapse').collapse('show')
- }
- )
+ id_icon.hidden = false
+ id_tick.hidden = true
+ id_cross.hidden = true
+ id_spinner.hidden = true
+ // the below causes an ugly flicker, so just keep the message
+ //id_message.hidden = true
- document.getElementById('step-2-back').addEventListener(
- 'click',
- () => {$('#step-1-collapse').collapse('show')}
- )
+ if (!id_form.checkValidity()) {
+ id_form.classList.add('was-validated');
- document.getElementById('step-2-sign-in').addEventListener(
- 'click',
- () => {document.getElementById('sign-in').click()}
+ id_icon.hidden = true
+ id_cross.hidden = false
+ return
+ }
+ id_form.classList.remove('was-validated');
+
+ let email = id_email.value.slice(0, 256).toLowerCase()
+ let link_code = id_link_code.value.slice(0, 32)
+
+ id_icon.hidden = true
+ id_spinner.hidden = false
+ try {
+ await api_call(
+ '/api/account/verify_email.json',
+ email,
+ link_code
+ )
+ }
+ catch (error) {
+ let problem = Problem.from(error)
+
+ id_cross.hidden = false
+ id_spinner.hidden = true
+
+ id_message.textContent = problem.detail
+ //id_message.classList.remove('text-success')
+ id_message.classList.add('text-danger')
+ id_message.hidden = false
+ return
+ }
+ id_tick.hidden = false
+ id_spinner.hidden = true
+ id_message.textContent = `Your email "${email}" has been verified. You can now sign in.`
+ //id_message.classList.add('text-success')
+ id_message.classList.remove('text-danger')
+ id_message.hidden = false
+ }
)
}
)