Update /my_account/password_reset/index.html.jst to latest way, no accordion
authorNick Downing <nick@ndcode.org>
Wed, 26 Jan 2022 01:30:31 +0000 (12:30 +1100)
committerNick Downing <nick@ndcode.org>
Wed, 26 Jan 2022 02:56:07 +0000 (13:56 +1100)
my_account/password_reset/index.html.jst

index f0ee4cf..55263ba 100644 (file)
@@ -1,18 +1,36 @@
-let logjson = (await import('@ndcode/logjson')).default
-
 return async env => {
   let breadcrumbs = await _require('/_lib/breadcrumbs.jst')
+  let fa_envelope = await env.site.get_min_svg('/_svg/fa_envelope.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)
-  console.log('details', JSON.stringify(details))
-
-  await navbar(
+  // 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) :
+      ''
+
+   await navbar(
     env,
     // head
     async _out => {},
@@ -22,154 +40,147 @@ return async env => {
 
       p {'To reset your password, please enter new details below and we will send you a password reset link.'}
 
-      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") {
-              'Account details'
+          }
+          div.col-md-6 {
+            div.form-group {
+              label.form-label(for="new-password") {'New password *'}
+              input.form-control#new-password(type="password" placeholder="Choose" required="required" minlength=8 maxlength=256) {}
+              div.invalid-feedback {'Please choose a secure password of at least 8 characters.'}
             }
           }
-          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="password") {'Password *'}
-                    input.form-control#password(type="password" placeholder="New password" required="required" minlength=8 maxlength=256) {}
-                  }
-                }
-              }
+        }
+      }
 
-              button.btn.btn-success#step-1-continue(type="button") {'Continue'}
-              p.'mt-3'.mb-0 {'* This field is required.'}
+      if (email.length)
+        button.btn.btn-success#password-reset(type="button") {
+          div.icon24-outer.mr-2#icon {
+            div.icon24-inner {_out.push(fa_envelope)}
+          }
+          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") {}
             }
           }
+          'Password reset'
         }
-        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") {
-              'Send password reset link'
-            }
+      else
+        button.btn.btn-success#password-reset(type="button" disabled) {
+          div.icon24-outer.mr-2#icon {
+            div.icon24-inner {_out.push(fa_envelope)}
           }
-          div#step-2-collapse.collapse(role="tabpanel" aria-labelledby="step-2-heading" data-parent="#accordion") {
-            div.card-body {
-              p#step-2-message {'Please enter account details first.'}
-
-              button.btn.btn-outline-secondary#step-2-back(type="button") {'Back'}
-              button.btn.btn-outline-secondary.ml-3#step-2-resend-email(type="button") {'Re-send email'}
+          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") {}
             }
           }
+          'Password reset'
         }
-      }
+
+      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('password').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/password_reset.json',
-              email,
-              document.getElementById('password').value.slice(0, 256)
-            )
-          }
-          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 = `Password reset link has been sent to "${email}". Please check your email for next steps.`
-          return true
-        }
-
         document.addEventListener(
           'DOMContentLoaded',
           () => {
-            document.getElementById('step-1-continue').addEventListener(
-              'click',
-              async () => {
-                if (await step_1() && await step_2())
-                  $('#step-2-collapse').collapse('show')
-              }
-            )
+            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_message = document.getElementById('message')
+            let id_new_password = document.getElementById('new-password')
+            let id_password_reset = document.getElementById('password-reset')
+            let id_spinner = document.getElementById('spinner')
+            let id_tick = document.getElementById('tick')
+
+            let edited = () => {
+              id_password_reset.disabled =
+                id_email.value.length === 0 &&
+                  id_new_password.value.length === 0
+              id_icon.hidden = false
+              id_tick.hidden = true
+              id_cross.hidden = true
+              id_spinner.hidden = true
+              id_message.hidden = true
+            }
 
-            document.getElementById('step-2-back').addEventListener(
-              'click',
-              () => {$('#step-1-collapse').collapse('show')}
-            )
+            id_email.addEventListener('input', edited)
+            id_new_password.addEventListener('input', edited)
 
-            document.getElementById('step-2-resend-email').addEventListener(
+            id_password_reset.addEventListener(
               'click',
               async () => {
-                if (await step_2())
-                  $('#step-3-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
+
+                if (!id_form.checkValidity()) {
+                  id_form.classList.add('was-validated');
+
+                  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 new_password = id_new_password.value.slice(0, 256)
+
+                id_icon.hidden = true
+                id_spinner.hidden = false
+                try {
+                  await api_call(
+                    '/api/account/password_reset.json',
+                    email,
+                    new_password
+                  )
+                }
+                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 = `Password reset link has been sent to "${email}". Please check your email for next steps.`
+                //id_message.classList.add('text-success')
+                id_message.classList.remove('text-danger')
+                id_message.hidden = false
               }
             )
           }