B4J Tutorial [ABMaterial]: Creating a Sign In Modal Dialog with Options: Part 2

Discussion in 'B4J Tutorials' started by Mashiane, Feb 20, 2018.

  1. Mashiane

    Mashiane Expert Licensed User

    Hi again

    This is the second installment of the above mentioned article. In this part we will look into the "Forgot Password" UX design and some additional things.

    Part 2.1



    Goal

    • When a user selects Forgot Password in the Sign In screen, the Forgot Password screen should appear.
    • The email entered by the user is compulsory. After the user enters their email address and selects Next
    • The email will be read from an existing user table and it found should be sent to the user via email.
    • The email settings for the smtp should be read from a pre-defined table and used to initialize smtp.
    • The user is provided an option to Try something else, this activates a screen to Change the password.

    Reproduction

    Creating a modal sheet is simple as discussed in the previous article about this activity.

    1.1 Creating this Forgot Password Modal Sheet.

    Code:
    Private Sub contLoginBuild() As ABMModalSheet
        
    Dim contLogin As ABMModalSheet
        contLogin.Initialize(
    page"contLogin"False, ABM.MODALSHEET_TYPE_NORMAL, "ms")
        contLogin.Size = ABM.MODALSHEET_SIZE_NORMAL
        contLogin.IsDismissible = 
    False
        contLogin.IsTextSelectable = 
    True
        contLogin.Content.AddRows(
    1,True,"").AddCells12(1"")
        contLogin.Content.AddRows(
    1,True,"").AddCellsOSMPV(10001212120000, ABM.VISIBILITY_ALL, "")
        contLogin.Content.AddRows(
    1,True,"").AddCellsOSMPV(100012121200100, ABM.VISIBILITY_ALL, "")
        contLogin.Content.AddRows(
    1,True,"").AddCellsOSMPV(10001212120000, ABM.VISIBILITY_ALL, "")
        contLogin.Content.AddRows(
    1,True,"").AddCellsOSMPV(100066600100, ABM.VISIBILITY_ALL, "").AddCellsOSMPV(1000666001010, ABM.VISIBILITY_ALL, "")
        contLogin.Header.BuildGrid  
    'IMPORTANT once you loaded the complete grid AND before you start adding components
        contLogin.Content.BuildGrid 'IMPORTANT once you loaded the complete grid AND before you start adding components
        contLogin.Footer.BuildGrid  'IMPORTANT once you loaded the complete grid AND before you start adding components
        'Add components to ModalSheet
        Dim lblTrySomethingElse As ABMLabel
        lblTrySomethingElse.Initialize(
    page"lblTrySomethingElse"$"{C:#993333}{I}Try something else?{/I}{/C}"$, ABM.SIZE_PARAGRAPH, False"")
        lblTrySomethingElse.Clickable = 
    True
        lblTrySomethingElse.SetCursor(ABM.CURSOR_POINTING)
        lblTrySomethingElse.istextselectable = 
    True
        lblTrySomethingElse.supportemoji = 
    False
        contLogin.Content.Cell(
    5,1).AddComponent(lblTrySomethingElse)
        
    Dim imglogo As ABMImage
        imglogo.Initialize(
    page"imglogo""../images/logo.png?"DateTime.Now, 1)
        imglogo.Tag = 
    "imglogo"
        imglogo.IsResponsive = 
    False
        imglogo.IsCircular = 
    False
        imglogo.IsClickable = 
    False
        imglogo.IsMaterialBoxed = 
    False
        contLogin.Content.Cell(
    2,1).AddComponent(imglogo)
        
    Dim txtemail As ABMInput
        txtemail.Initialize(
    page"txtemail", ABM.INPUT_EMAIL, "Email Address"False"")
        txtemail.Tag = 
    "txtemail"
        contLogin.Content.Cell(
    4,1).AddComponent(txtemail)
        
    Dim btnNext As ABMButton
        btnNext.InitializeRaised(
    page"btnNext""""""Next""")
        btnNext.Tag = 
    "btnNext"
        btnNext.UseFullCellWidth = 
    True
        btnNext.Size = ABM.BUTTONSIZE_NORMAL
        btnNext.dropdownhidearrow = 
    False
        btnNext.dropdownshowbelow = 
    False
        btnNext.dropdownconstrainwidth = 
    False
        contLogin.Content.Cell(
    5,2).AddComponent(btnNext)
        
    Dim lblheader As ABMLabel
        lblheader.Initialize(
    page"lblheader"$"{B}Account help{/B}"$, ABM.SIZE_PARAGRAPH, False"")
        lblheader.istextselectable = 
    True
        lblheader.supportemoji = 
    False
        contLogin.Content.Cell(
    3,1).AddComponent(lblheader)
        
    Dim lblsubheader As ABMLabel
        lblsubheader.Initialize(
    page"lblsubheader"$"If {B}registered{/B} with us, your password will be emailed"$, ABM.SIZE_PARAGRAPH, False"")
        lblsubheader.istextselectable = 
    True
        lblsubheader.supportemoji = 
    False
        contLogin.Content.Cell(
    3,1).AddComponent(lblsubheader)
        
    Return contLogin
    End Sub
    Next we call this method on BuildPage and then show the ModalSheet when the page is connected. As the email is compulsory we need to validate it too.

    Code:
    'Get the contents of the modal sheet input components and save to a map
    Sub contLoginGetContents() As Map
        
    Dim pMap As Map
        pMap.Initialize
        
    Dim contLogin As ABMModalSheet
        contLogin = 
    page.ModalSheet("contLogin")
        
    Dim txtemail As ABMInput = contLogin.Content.Component("txtemail")
        pMap.put(
    "email", txtemail.Text)
        
    Return pMap
    End Sub
    'Get the contents of the modal sheet from GetContents and check validity
    Sub contLoginValidate(gMap As MapAs Boolean
        
    Dim contLogin As ABMModalSheet
        contLogin = 
    page.ModalSheet("contLogin")
        
    Dim stxtemail As String
        stxtemail = gMap.get(
    "email")
        
    If stxtemail = "null" Then stxtemail = ""
        
    If stxtemail.Length = 0 Then
            ABMShared.Warn(
    page,"Email Address cannot be blank. Please enter a value.")
            
    Dim txtemail As ABMInput = contLogin.Content.Component("txtemail")
            txtemail.SetFocus
            
    Return False
        
    End If
        
    Return True
    End Sub
    As soon as the Next Button is selected, the process of verifying the entered email address against the database starts.

    Code:
    'An ABMButton has been clicked
    Sub btnNext_Clicked(Target As String)
        
    Wait For (contLoginForgotPassword) Complete(Result As Boolean)
        
    If Result = False Then Return
        ABMShared.NavigateToPage(ws, ABMPageId, 
    "../frmTellForgotPassword/frmTellForgotPassword.html")
    End Sub
    the contLoginForgotPassword sub is called. I decided to try out a ResumableSub inside an ABMaterial project. The code compiles well.

    Code:
    Private Sub contLoginForgotPassword() As ResumableSub
        
    'define a map to hold the form contents
        Dim m As Map
        
    'read the form contents to a map
        m = contLoginGetContents
        
    Dim email As String
        
    email = m.get("email")
        
    If email = "null" Then email = ""
        
    If email.Length = 0 Then
            ABMShared.Warn(
    page,"Email cannot be blank. Please enter a value.")
            
    Return False
        
    End If
        
    'the form contents are ok, send login credentials to user
        'define the search criteria, fields must equal
        Dim w As Map
        
    Dim nk As String
        w.Initialize
        nk = 
    "email="
        w.put(nk, 
    email)
        
    'Get connection from current pool if MySQL/MSSQL
        Dim jSQL As SQL = ABMShared.SQLGet
        
    Dim UserMap As Map = ABMShared.SQLSelectRecordWhereMap(jSQL,"users", w)
        
    If UserMap.IsInitialized = False Then
            ABMShared.Warn(
    page,"The Email specified could not be found in our records, please specify the correct email.")
            
    Return False
        
    End If
        
    'The email has been found, send the details to the user
        Dim username As String
        username = UserMap.get(
    "username")
        
    Dim password As String
        password = UserMap.get(
    "password")
        
    Try
            
    ' start smtp to send the emails
            Dim sbody As String = "Good Day||Someone or you requested your Sign In credentials.||Your UserName is: " & username & "||Your Password is: " & password & "||Development Team|"
            sbody = ABMShared.Replace(sbody,
    "|",CRLF)
            
    Wait For (ABMShared.SendEmail(email"askteencoach: Sign In Credentials", sbody)) Complete(Result As Boolean)
            
    If Result = False Then
                myToastId = myToastId + 
    1
                
    page.ShowToast("toast" & myToastId, "toastred""Sign In Credentials could not be emailed!"3000,False)
            
    Else
                myToastId = myToastId + 
    1
                
    page.ShowToast("toast" & myToastId, "toastgreen""Sign In Credentials emailed successfully."3000,False)
            
    End If
            
    'Close the connection to the database
            ABMShared.SQLClose(jSQL)
            
    Return Result
        
    Catch
            myToastId = myToastId + 
    1
            
    page.ShowToast("toast" & myToastId, "toastred""Email could not be sent, please try again."3000,False)
            
    Return False
        
    End Try
    End Sub
    The above code, gets the contents of the modal sheet, checks if its valid and also verifies it against a database. When the user record is found that matches the email address, the password is read and these are sent to the user via email. The sub call is SendEmail saved in ABMShared.

    Code:
    Sub GetEmailSettings() As Map
        
    Dim es As Map
        es.Initialize
        
    Dim jSQL As SQL = SQLGet
        
    'get first available account, there should be 1
        Dim id As String = SQLSelectSingleResult(jSQL, "select id from EmailAccounts where active = 1"Null)
        
    If id = "" Then Return es
        
    'read the email settings first
        es = SQLRecordRead(jSQL,"EmailAccounts""id"id)
        
    Return es
    End Sub
    Sub SendEmail(toEmail As String, subject As String, msg As StringAs ResumableSub
        
    Try
            
    'read the email settings first
            Dim es As Map = GetEmailSettings
            
    Dim sserver As String = es.GetDefault("server","")
            
    Dim sport As String = es.GetDefault("port","25")
            
    Dim susername As String = es.GetDefault("username","")
            
    Dim spassword As String = es.GetDefault("password","")
            
    Dim sStartTLSMode As String = es.GetDefault("starttlsmode","0")
            
    Dim sUseSSL As String = es.GetDefault("usessl","0")
            
    'start sending the email
            esmtp.Initialize(sserver, sport, susername, spassword, "smtp")
            esmtp.To.Add(toEmail)
            esmtp.Body = msg
            esmtp.Subject = subject
            
    If sStartTLSMode = "1" Then
                esmtp.StartTLSMode = 
    True
            
    Else
                esmtp.StartTLSMode = 
    False
            
    End If
            
    If sUseSSL = "1" Then
                esmtp.UseSSL = 
    True
            
    Else
                esmtp.UseSSL = 
    False
            
    End If
            
    Wait For (esmtp.Send) smtp_MessageSent(Success As Boolean)
            
    Return Success
        
    Catch
            
    Return False
        
    End Try
    End Sub
    Sub smtp_MessageSent(Success As Boolean)
        
    Log(Success)
    End Sub
    The EmailAccounts table stores settings for email accounts that can be used to send emails in our app. There can only be 1 active account to send emails from at anytime. The settings are read from that table, these provide the smtp server, the port, the username and password to use to send the email.

    I usually test these settings via b4j first and then save them as default in my webapp.

    The option to try something else has been provided to enable the user to change their password, should they remember it. This will be Part 2.1 of this article.

    Disclaimer:

    This article is mostly about UX design with specific attention to ModalSheets for this purpose. A try to work with ResumableSub was undertaken here to send the email to the user. For now its still a dololo experience. #investigating. The header/footer components of the ModalSheet are not used for this exercise. The adding of the components on the modal sheet is not sequential (this is not recommended) as on ConnectPage, the last modalsheet element is added then others added after. ;)

    Related Article: Enabling Users to get their lost passwords


    Ta!
     

    Attached Files:

    Last edited: Feb 22, 2018
    clarionero, amaxco, OliverA and 4 others like this.
  2. Mashiane

    Mashiane Expert Licensed User

    To close off, you can create a free account at www.smtp2go.com and use the provided settings to test your account. A free account limits to 25 emails per hour. #as of writing.
     
Loading...
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice