1 let logjson = (await import('@ndcode/logjson')).default
4 let breadcrumbs = await _require('/_lib/breadcrumbs.jst')
5 let icon_cross = await env.site.get_min_svg('/_svg/icon_cross.svg')
6 let icon_tick = await env.site.get_min_svg('/_svg/icon_tick.svg')
7 let navbar = await _require('/_lib/navbar.jst')
8 let session_cookie = await _require('/_lib/session_cookie.jst')
10 // preload draft details if any
11 let transaction = await env.site.database.Transaction(), details
13 // initialize env.session_key, set cookie in env.response
14 let session = await session_cookie(env, transaction)
16 details = await logjson.logjson_to_json(
17 await session.get('sign_up_draft', {})
21 transaction.rollback()
23 console.log('details', JSON.stringify(details))
31 await breadcrumbs(env, _out)
33 p {'Signing up allows you to leave comments on our blog and receive communications from us.'}
35 div.accordion#accordion.mb-5(role="tablist" aria-multiselectable="true") {
37 div.card-header#step-1-heading(role="tab") {
38 span#step-1-tick(style="display: none;") {
39 span.icon-color.pr-3 {_out.push(icon_tick)}
41 span#step-1-cross(style="display: none;") {
42 span.icon-color.pr-3 {_out.push(icon_cross)}
44 //span#step-1-spinner(style="display: none;") {
45 // span.icon-color.pr-3 {
46 // div.spinner-border(role="status") {
47 // span.sr-only {'Loading...'}
51 a.h5(data-toggle="collapse" data-parent="#accordion" href="#step-1-collapse" aria-expanded="true" aria-controls="step-1-collapse") {
55 div#step-1-collapse.collapse.show(role="tabpanel" aria-labelledby="step-1-heading" data-parent="#accordion") {
60 label.form-label(for="given-names") {'Given names *'}
61 input.form-control#given-names(type="text" value=details.given_names || '' placeholder="Your given names" required="required" maxlength=256) {}
66 label.form-label(for="family-name") {'Family name'}
67 input.form-control#family-name(type="text" value=details.family_name || '' placeholder="Your family name" maxlength=256) {}
74 label.form-label(for="email") {'Email *'}
75 input.form-control#email(type="email" value=details.email || '' placeholder="Your email address" required="required" maxlength=256) {}
80 label.form-label(for="password") {'Password *'}
81 input.form-control#password(type="password" value=details.password || '' placeholder="New password" required="required" minlength=8 maxlength=256) {}
87 div.custom-control.custom-checkbox {
88 if (details.contact_me === undefined || details.contact_me)
89 input.custom-control-input#contact-me(type="checkbox" checked="checked") {}
91 input.custom-control-input#contact-me(type="checkbox") {}
93 label.custom-control-label(for="contact-me") {
94 'Contact me by email with updates and special offers'
99 div.row.align-items-center {
102 label.form-label(for="verification-code") {'Verification code *'}
103 input.form-control#verification-code(type="text" placeholder="Type the code shown to the right" required="required" minlength=6 maxlength=6) {}
107 img#verification-image(src="/api/verification_image.png?seq=0" width=300 height=150) {}
109 div.'col-md-2'.my-auto.text-center {
110 input.btn.btn-outline-secondary#'step-1-new-code'(type="button" value="New code") {}
114 p.mt-3 {'Note: If your name is one word or does not fit given names/family name pattern, then please enter given names only. Your given names are visible to other users if you comment on our blog. Your email and family name remain private.'}
116 input.btn.btn-success#step-1-continue(type="button" value="Continue") {}
117 p.'mt-3'.mb-0 {'* These fields are required.'}
122 div.card-header#step-2-heading(role="tab") {
123 span#step-2-tick(style="display: none;") {
124 span.icon-color.pr-3 {_out.push(icon_tick)}
126 span#step-2-cross(style="display: none;") {
127 span.icon-color.pr-3 {_out.push(icon_cross)}
129 span#step-2-spinner(style="display: none;") {
130 span.icon-color.pr-3 {
131 div.spinner-border(role="status") {
132 span.sr-only {'Loading...'}
136 a.h5.collapsed(data-toggle="collapse" data-parent="#accordion" href="#step-2-collapse" aria-expanded="false" aria-controls="step-2-collapse") {
140 div#step-2-collapse.collapse(role="tabpanel" aria-labelledby="step-2-heading" data-parent="#accordion") {
142 p#step-2-message {'Please enter your details first.'}
144 input.btn.btn-outline-secondary#step-2-back(type="button" value="Back") {}
145 input.btn.btn-outline-secondary.ml-3#step-2-continue(type="button" value="Continue") {}
150 div.card-header#step-3-heading(role="tab") {
151 span#step-3-tick(style="display: none;") {
152 span.icon-color.pr-3 {_out.push(icon_tick)}
154 span#step-3-cross(style="display: none;") {
155 span.icon-color.pr-3 {_out.push(icon_cross)}
157 span#step-3-spinner(style="display: none;") {
158 span.icon-color.pr-3 {
159 div.spinner-border(role="status") {
160 span.sr-only {'Loading...'}
164 a.h5.collapsed(data-toggle="collapse" data-parent="#accordion" href="#step-3-collapse" aria-expanded="false" aria-controls="step-3-collapse") {
165 'Send verification email'
168 div#step-3-collapse.collapse(role="tabpanel" aria-labelledby="step-3-heading" data-parent="#accordion") {
170 p#step-3-message {'Please create your account first.'}
172 input.btn.btn-outline-secondary#step-3-back(type="button" value="Back") {}
173 input.btn.btn-outline-secondary.ml-3#step-3-resend-email(type="button" value="Resend email") {}
181 script(src="/js/api_call.js") {}
184 let sign_up_create_account = async (...arguments) => api_call(
185 '/api/sign_up/create_account.json',
188 //let sign_up_get_draft = async (...arguments) => api_call(
189 // '/api/sign_up/get_draft.json',
192 let sign_up_set_draft = async (...arguments) => api_call(
193 '/api/sign_up/set_draft.json',
196 let sign_up_send_verification_email = async (...arguments) => api_call(
197 '/api/sign_up/send_verification_email.json',
201 let coerce_details = () => {
203 email: document.getElementById('email').value.slice(0, 256).toLowerCase(),
204 given_names: document.getElementById('given-names').value.slice(0, 256),
205 family_name: document.getElementById('family-name').value.slice(0, 256),
206 password: document.getElementById('password').value.slice(0, 256),
207 contact_me: document.getElementById('contact-me').checked ? true : false
211 let draft_timeout_running = false
212 let draft_timeout_handler = async () => {
213 draft_timeout_running = false
214 await sign_up_set_draft(coerce_details())
215 //console.log('draft', await sign_up_get_draft())
217 let draft_change_handler = () => {
218 if (!draft_timeout_running) {
219 draft_timeout_running = true
220 setTimeout(draft_timeout_handler, 5000)
224 let step_1 = async () => {
226 !document.getElementById('given-names').reportValidity() ||
227 !document.getElementById('family-name').reportValidity() ||
228 !document.getElementById('email').reportValidity() ||
229 !document.getElementById('password').reportValidity() ||
230 !document.getElementById('verification-code').reportValidity()
232 $('#step-1-tick').hide()
233 $('#step-1-cross').show()
234 //$('#step-1-spinner').hide()
237 $('#step-1-tick').show()
238 $('#step-1-cross').hide()
239 //$('#step-1-spinner').hide()
243 let step_2_details = ''
244 let step_2 = async () => {
245 $('#step-2-tick').hide()
246 $('#step-2-cross').hide()
247 $('#step-2-spinner').show()
249 step_2_details = coerce_details()
250 await sign_up_create_account(
252 document.getElementById('verification-code').value.slice(0, 6).toLowerCase(),
258 $('#step-2-tick').hide()
259 $('#step-2-cross').show()
260 $('#step-2-spinner').hide()
262 document.getElementById('step-2-message').textContent = e.message
263 $('#step-2-collapse').collapse('show')
266 $('#step-2-tick').show()
267 $('#step-2-cross').hide()
268 $('#step-2-spinner').hide()
270 document.getElementById('step-2-message').textContent = `Your account with email "${step_2_details.email}" has been created.`
274 let step_3 = async () => {
275 $('#step-3-tick').hide()
276 $('#step-3-cross').hide()
277 $('#step-3-spinner').show()
279 await sign_up_send_verification_email(step_2_details.email)
282 $('#step-3-tick').hide()
283 $('#step-3-cross').show()
284 $('#step-3-spinner').hide()
286 document.getElementById('step-3-message').textContent = e.message
287 $('#step-3-collapse').collapse('show')
290 $('#step-3-tick').show()
291 $('#step-3-cross').hide()
292 $('#step-3-spinner').hide()
294 document.getElementById('step-3-message').textContent = `Verification email has been sent to "${step_2_details.email}". Please check your email for next steps.`
298 document.addEventListener(
301 document.getElementById('given-names').addEventListener(
305 document.getElementById('family-name').addEventListener(
309 document.getElementById('email').addEventListener(
313 document.getElementById('password').addEventListener(
317 document.getElementById('contact-me').addEventListener(
323 document.getElementById('step-1-new-code').addEventListener(
326 document.getElementById('verification-image').src = `/api/verification_image.png?seq=${image_seq}`
331 document.getElementById('step-1-continue').addEventListener(
334 if (await step_1() && await step_2() && await step_3())
335 $('#step-3-collapse').collapse('show')
339 document.getElementById('step-2-back').addEventListener(
341 () => {$('#step-1-collapse').collapse('show')}
344 document.getElementById('step-2-continue').addEventListener(
348 $('#step-3-collapse').collapse('show')
352 document.getElementById('step-3-back').addEventListener(
354 () => {$('#step-2-collapse').collapse('show')}
357 document.getElementById('step-3-resend-email').addEventListener(
361 $('#step-3-collapse').collapse('show')