1 let XDate = require('xdate')
4 let breadcrumbs = await _require('/_lib/breadcrumbs.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 draft details if any
11 let transaction = await env.site.database.Transaction()
14 let root = await transaction.get({})
15 let session = await get_session(env, root)
17 let sign_up_draft = await session.get('sign_up_draft')
19 sign_up_draft !== undefined &&
20 XDate.now() < await sign_up_draft.get_json('expires') ?
22 email: await sign_up_draft.get_json('email'),
23 given_names: await sign_up_draft.get_json('given_names'),
24 family_name: await sign_up_draft.get_json('family_name'),
25 contact_me: await sign_up_draft.get_json('contact_me')
30 transaction.rollback()
32 console.log('draft_details', JSON.stringify(draft_details))
40 await breadcrumbs(env, _out)
42 p {'Signing up allows you to leave comments on our blog and receive communications from us.'}
44 p {'Your given names are visible to other users if you comment on our blog. Your email and family name remain private. If your name is one word or does not fit given names/family name pattern, then please enter given names only.'}
46 div.accordion#accordion.mb-5(role="tablist" aria-multiselectable="true") {
48 div.card-header#step-1-heading(role="tab") {
49 span#step-1-tick(style="display: none;") {
50 span.icon-color.pr-3 {_out.push(icon_tick)}
52 span#step-1-cross(style="display: none;") {
53 span.icon-color.pr-3 {_out.push(icon_cross)}
55 //span#step-1-spinner(style="display: none;") {
56 // span.icon-color.pr-3 {
57 // div.spinner-border(role="status") {
58 // span.sr-only {'Loading...'}
62 a.h5(data-toggle="collapse" data-parent="#accordion" href="#step-1-collapse" aria-expanded="true" aria-controls="step-1-collapse") {
66 div#step-1-collapse.collapse.show(role="tabpanel" aria-labelledby="step-1-heading" data-parent="#accordion") {
71 label.form-label(for="given-names") {'Given names *'}
72 input.form-control#given-names(type="text" value=draft_details ? draft_details.given_names : '' placeholder="Your given names" required="required" maxlength=256) {}
77 label.form-label(for="family-name") {'Family name'}
78 input.form-control#family-name(type="text" value=draft_details ? draft_details.family_name : '' placeholder="Your family name" maxlength=256) {}
85 label.form-label(for="email") {'Email *'}
86 input.form-control#email(type="email" value=draft_details ? draft_details.email : '' placeholder="Your email address" required="required" maxlength=256) {}
91 label.form-label(for="password") {'Password *'}
92 input.form-control#password(type="password" placeholder="New password" required="required" minlength=8 maxlength=256) {}
98 div.custom-control.custom-checkbox {
99 if (!draft_details || draft_details.contact_me)
100 input.custom-control-input#contact-me(type="checkbox" checked="checked") {}
102 input.custom-control-input#contact-me(type="checkbox") {}
104 label.custom-control-label(for="contact-me") {
105 'Contact me by email with updates and special offers'
110 div.row.align-items-center.mb-3 {
113 label.form-label(for="verification-code") {'Verification code *'}
114 input.form-control#verification-code(type="text" placeholder="Type the code shown to the right" required="required" minlength=6 maxlength=6) {}
118 img#verification-image(src="/api/verification_image.png?seq=0" width=300 height=150) {}
120 div.'col-md-2'.my-auto.text-center {
121 button.btn.btn-outline-secondary#'step-1-new-code'(type="button") {'New code'}
125 button.btn.btn-success#step-1-continue(type="button") {'Continue'}
127 p.'mt-3'.mb-0 {'* These fields are required.'}
132 div.card-header#step-2-heading(role="tab") {
133 span#step-2-tick(style="display: none;") {
134 span.icon-color.pr-3 {_out.push(icon_tick)}
136 span#step-2-cross(style="display: none;") {
137 span.icon-color.pr-3 {_out.push(icon_cross)}
139 span#step-2-spinner(style="display: none;") {
140 span.icon-color.pr-3 {
141 div.spinner-border(role="status") {
142 span.sr-only {'Loading...'}
146 a.h5.collapsed(data-toggle="collapse" data-parent="#accordion" href="#step-2-collapse" aria-expanded="false" aria-controls="step-2-collapse") {
150 div#step-2-collapse.collapse(role="tabpanel" aria-labelledby="step-2-heading" data-parent="#accordion") {
152 p#step-2-message {'Please enter your details first.'}
154 button.btn.btn-outline-secondary#step-2-back(type="button") {'Back'}
155 button.btn.btn-outline-secondary.ml-3#step-2-continue(type="button") {'Continue'}
160 div.card-header#step-3-heading(role="tab") {
161 span#step-3-tick(style="display: none;") {
162 span.icon-color.pr-3 {_out.push(icon_tick)}
164 span#step-3-cross(style="display: none;") {
165 span.icon-color.pr-3 {_out.push(icon_cross)}
167 span#step-3-spinner(style="display: none;") {
168 span.icon-color.pr-3 {
169 div.spinner-border(role="status") {
170 span.sr-only {'Loading...'}
174 a.h5.collapsed(data-toggle="collapse" data-parent="#accordion" href="#step-3-collapse" aria-expanded="false" aria-controls="step-3-collapse") {
175 'Send email verification link'
178 div#step-3-collapse.collapse(role="tabpanel" aria-labelledby="step-3-heading" data-parent="#accordion") {
180 p#step-3-message {'Please create your account first.'}
182 button.btn.btn-outline-secondary#step-3-back(type="button") {'Back'}
183 button.btn.btn-outline-secondary.ml-3#step-3-resend-email(type="button") {'Re-send email'}
191 //script(src="/js/api_call.js") {}
194 let draft_timeout_running = false
195 let draft_timeout_handler = async () => {
196 draft_timeout_running = false
198 '/api/account/sign_up/set_draft.json',
200 email: document.getElementById('email').value.slice(0, 256).toLowerCase(),
201 given_names: document.getElementById('given-names').value.slice(0, 256),
202 family_name: document.getElementById('family-name').value.slice(0, 256),
203 contact_me: document.getElementById('contact-me').checked ? true : false
206 //console.log('draft', await api_call('/api/account/sign_up/get_draft.json'))
208 let draft_change_handler = () => {
209 if (!draft_timeout_running) {
210 draft_timeout_running = true
211 setTimeout(draft_timeout_handler, 5000)
216 let step_1 = async () => {
218 !document.getElementById('given-names').reportValidity() ||
219 !document.getElementById('family-name').reportValidity() ||
220 !document.getElementById('email').reportValidity() ||
221 !document.getElementById('password').reportValidity() ||
222 !document.getElementById('verification-code').reportValidity()
224 $('#step-1-tick').hide()
225 $('#step-1-cross').show()
226 //$('#step-1-spinner').hide()
229 $('#step-1-tick').show()
230 $('#step-1-cross').hide()
231 //$('#step-1-spinner').hide()
234 email: document.getElementById('email').value.slice(0, 256).toLowerCase(),
235 given_names: document.getElementById('given-names').value.slice(0, 256),
236 family_name: document.getElementById('family-name').value.slice(0, 256),
237 password: document.getElementById('password').value.slice(0, 256),
238 contact_me: document.getElementById('contact-me').checked ? true : false
243 let step_2 = async () => {
244 $('#step-2-tick').hide()
245 $('#step-2-cross').hide()
246 $('#step-2-spinner').show()
247 document.getElementById('step-2').scrollIntoView()
251 '/api/account/sign_up/create_account.json',
252 document.getElementById('verification-code').value.slice(0, 6).toLowerCase(),
257 let problem = Problem.from(error)
259 $('#step-2-tick').hide()
260 $('#step-2-cross').show()
261 $('#step-2-spinner').hide()
263 document.getElementById('step-2-message').textContent = problem.detail
264 $('#step-2-collapse').collapse('show')
267 $('#step-2-tick').show()
268 $('#step-2-cross').hide()
269 $('#step-2-spinner').hide()
270 document.getElementById('step-2-message').textContent = `Your account with email "${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()
278 document.getElementById('step-3').scrollIntoView()
282 '/api/account/sign_up/send_email_verification_link.json',
287 let problem = Problem.from(error)
289 $('#step-3-tick').hide()
290 $('#step-3-cross').show()
291 $('#step-3-spinner').hide()
293 document.getElementById('step-3-message').textContent = problem.detail
294 $('#step-3-collapse').collapse('show')
297 $('#step-3-tick').show()
298 $('#step-3-cross').hide()
299 $('#step-3-spinner').hide()
301 document.getElementById('step-3-message').textContent = `Email verification link has been sent to "${details.email}". Please check your email for next steps.`
305 document.addEventListener(
308 document.getElementById('given-names').addEventListener(
312 document.getElementById('family-name').addEventListener(
316 document.getElementById('email').addEventListener(
320 document.getElementById('password').addEventListener(
324 document.getElementById('contact-me').addEventListener(
330 document.getElementById('step-1-new-code').addEventListener(
333 document.getElementById('verification-image').src = `/api/verification_image.png?seq=${image_seq}`
338 document.getElementById('step-1-continue').addEventListener(
341 if (await step_1() && await step_2() && await step_3())
342 $('#step-3-collapse').collapse('show')
346 document.getElementById('step-2-back').addEventListener(
348 () => {$('#step-1-collapse').collapse('show')}
351 document.getElementById('step-2-continue').addEventListener(
355 $('#step-3-collapse').collapse('show')
359 document.getElementById('step-3-back').addEventListener(
361 () => {$('#step-2-collapse').collapse('show')}
364 document.getElementById('step-3-resend-email').addEventListener(
368 $('#step-3-collapse').collapse('show')