11/* global window */
22
3- import React , { Component } from 'react' ;
3+ import React , { useState } from 'react' ;
44import PropTypes from 'prop-types' ;
55import { QRCodeSVG } from 'qrcode.react' ;
66import { formatCode } from 'lib/formatCode' ;
@@ -15,222 +15,172 @@ const VIEWS = {
1515 * This component provides the user interface for registering one-time time-based passwords (TOTP)
1616 * with a user.
1717 */
18- class Register extends Component {
19- constructor ( props ) {
20- super ( props ) ;
21-
22- this . state = {
23- error : props . error ,
24- view : props . error ? VIEWS . VALIDATE : VIEWS . SCAN ,
25- } ;
26-
27- this . handleBack = this . handleBack . bind ( this ) ;
28- this . handleBackToScan = this . handleBackToScan . bind ( this ) ;
29- this . handleNext = this . handleNext . bind ( this ) ;
30- }
18+ function Register ( props ) {
19+ const {
20+ code,
21+ onBack,
22+ onCompleteRegistration,
23+ error,
24+ errors,
25+ method,
26+ uri,
27+ TOTPVerifyComponent,
28+ } = props ;
29+ const [ stateError , setStateError ] = useState ( error ) ;
30+ const [ view , setView ] = useState ( error ? VIEWS . VALIDATE : VIEWS . SCAN ) ;
31+ const i18n = window . ss . i18n ;
3132
3233 /**
3334 * Send the user back to the "select method" screen
3435 */
35- handleBack ( ) {
36- this . props . onBack ( ) ;
36+ function handleBack ( ) {
37+ onBack ( ) ;
3738 }
3839
3940 /**
4041 * Send the user back to the "scan QR code" screen
4142 */
42- handleBackToScan ( ) {
43- this . setState ( {
44- view : VIEWS . SCAN ,
45- error : null ,
46- } ) ;
43+ function handleBackToScan ( ) {
44+ setView ( VIEWS . SCAN ) ;
45+ setStateError ( null ) ;
4746 }
4847
4948 /**
5049 * After user has scanned the QR code, handle the transition to the verify screen
5150 */
52- handleNext ( ) {
53- this . setState ( { view : VIEWS . VALIDATE } ) ;
51+ function handleNext ( ) {
52+ setView ( VIEWS . VALIDATE ) ;
5453 }
5554
5655 /**
5756 * Renders an action button menu with a Next and Back button, using a different handler for
5857 * the click of each button depending on which view we're in.
59- *
60- * @returns {HTMLElement }
6158 */
62- renderActionsMenu ( ) {
63- const { ss : { i18n } } = window ;
64-
65- return (
66- < ul className = "mfa-action-list" >
67- < li className = "mfa-action-list__item" >
68- < button
69- type = "button"
70- className = "btn btn-primary"
71- onClick = { this . handleNext }
72- >
73- { i18n . _t ( 'TOTPRegister.NEXT' , 'Next' ) }
74- </ button >
75- </ li >
76- < li className = "mfa-action-list__item" >
77- < button
78- type = "button"
79- className = "btn btn-secondary"
80- onClick = { this . handleBack }
81- >
82- { i18n . _t ( 'TOTPRegister.BACK' , 'Back' ) }
83- </ button >
84- </ li >
85- </ ul >
86- ) ;
59+ function renderActionsMenu ( ) {
60+ return < ul className = "mfa-action-list" >
61+ < li className = "mfa-action-list__item" >
62+ < button
63+ type = "button"
64+ className = "btn btn-primary"
65+ onClick = { handleNext }
66+ >
67+ { i18n . _t ( 'TOTPRegister.NEXT' , 'Next' ) }
68+ </ button >
69+ </ li >
70+ < li className = "mfa-action-list__item" >
71+ < button
72+ type = "button"
73+ className = "btn btn-secondary"
74+ onClick = { handleBack }
75+ >
76+ { i18n . _t ( 'TOTPRegister.BACK' , 'Back' ) }
77+ </ button >
78+ </ li >
79+ </ ul > ;
8780 }
8881
8982 /**
9083 * Handles rendering of errors returned from the backend API requests, e.g.
9184 * your session has timed out.
92- *
93- * @returns {HTMLElement }
9485 */
95- renderErrorScreen ( ) {
96- const { errors } = this . props ;
97-
86+ function renderErrorScreen ( ) {
9887 if ( ! errors . length ) {
9988 return null ;
10089 }
90+ return < div className = "mfa-totp__errors" >
91+ { errors . join ( ', ' ) }
92+ </ div > ;
93+ }
10194
102- return (
103- < div className = "mfa-totp__errors" >
104- { errors . join ( ', ' ) }
105- </ div >
106- ) ;
95+ /**
96+ * If there is a configured support link, will render a link to the TOTP authenticator's
97+ * support documentation (e.g. userhelp).
98+ */
99+ function renderSupportLink ( ) {
100+ const { supportLink, supportText } = method ;
101+ if ( ! supportLink ) {
102+ return null ;
103+ }
104+ return < a href = { supportLink } target = "_blank" rel = "noopener noreferrer" >
105+ { supportText || i18n . _t ( 'TOTPRegister.HOW_TO_USE' , 'How to use authenticator apps.' ) }
106+ </ a > ;
107107 }
108108
109109 /**
110110 * Renders the screen to scan a QR code with an authenticator app.
111- *
112- * @returns {HTMLElement }
113111 */
114- renderScanCodeScreen ( ) {
115- const { uri, code, errors } = this . props ;
116- const { view } = this . state ;
117- const { ss : { i18n } } = window ;
118-
112+ function renderScanCodeScreen ( ) {
119113 if ( view !== VIEWS . SCAN || errors . length ) {
120114 return null ;
121115 }
122-
123116 const formattedCode = formatCode ( code ) ;
124-
125- return (
126- < div >
127- < div className = "mfa-totp__scan" >
128- < p > { i18n . _t (
129- 'TOTPRegister.INTRO' ,
130- 'Verification codes are created by an app on your phone. '
131- ) } { this . renderSupportLink ( ) } </ p >
132-
133- < div className = "mfa-totp__scan-code" >
134- < div className = "mfa-totp__scan-left" >
135- < QRCodeSVG value = { uri } size = { 160 } />
136- </ div >
137-
138- < div className = "mfa-totp__scan-middle" >
139- { i18n . _t ( 'TOTPRegister.OR' , 'Or' ) }
140- </ div >
141-
142- < div className = "mfa-totp__scan-right" >
143- < p > { i18n . _t (
144- 'TOTPRegister.MANUAL' ,
145- 'Enter manually the following code into authentication app:'
146- ) } </ p >
147- < p className = "mfa-totp__manual-code" >
148- { formattedCode }
149- </ p >
150- </ div >
117+ return < div >
118+ < div className = "mfa-totp__scan" >
119+ < p > { i18n . _t (
120+ 'TOTPRegister.INTRO' ,
121+ 'Verification codes are created by an app on your phone. '
122+ ) } { renderSupportLink ( ) } </ p >
123+ < div className = "mfa-totp__scan-code" >
124+ < div className = "mfa-totp__scan-left" >
125+ < QRCodeSVG value = { uri } size = { 160 } />
126+ </ div >
127+ < div className = "mfa-totp__scan-middle" >
128+ { i18n . _t ( 'TOTPRegister.OR' , 'Or' ) }
129+ </ div >
130+ < div className = "mfa-totp__scan-right" >
131+ < p > { i18n . _t (
132+ 'TOTPRegister.MANUAL' ,
133+ 'Enter manually the following code into authentication app:'
134+ ) } </ p >
135+ < p className = "mfa-totp__manual-code" >
136+ { formattedCode }
137+ </ p >
151138 </ div >
152139 </ div >
153- { this . renderActionsMenu ( ) }
154140 </ div >
155- ) ;
156- }
157-
158- /**
159- * If there is a configured support link, will render a link to the TOTP authenticator's
160- * support documentation (e.g. userhelp).
161- *
162- * @returns {HTMLElement }
163- */
164- renderSupportLink ( ) {
165- const { method : { supportLink, supportText } } = this . props ;
166- const { ss : { i18n } } = window ;
167-
168- if ( ! supportLink ) {
169- return null ;
170- }
171-
172- return (
173- < a href = { supportLink } target = "_blank" rel = "noopener noreferrer" >
174- { supportText || i18n . _t ( 'TOTPRegister.HOW_TO_USE' , 'How to use authenticator apps.' ) }
175- </ a >
176- ) ;
141+ { renderActionsMenu ( ) }
142+ </ div > ;
177143 }
178144
179145 /**
180146 * The back button for the verification screen should send you back to the register screen
181- *
182- * @return HTMLElement|null
183147 */
184- renderBackButtonForVerify ( ) {
185- const { ss : { i18n } } = window ;
186-
187- return (
188- < button
189- type = "button"
190- className = "mfa-actions__action mfa-actions__action--back btn btn-secondary"
191- onClick = { this . handleBackToScan }
192- >
193- { i18n . _t ( 'TOTPRegister.BACK' , 'Back' ) }
194- </ button >
195- ) ;
148+ function renderBackButtonForVerify ( ) {
149+ return < button
150+ type = "button"
151+ className = "mfa-actions__action mfa-actions__action--back btn btn-secondary"
152+ onClick = { handleBackToScan }
153+ >
154+ { i18n . _t ( 'TOTPRegister.BACK' , 'Back' ) }
155+ </ button > ;
196156 }
197157
198158 /**
199159 * Renders the screen to input and validate the TOTP code, after having registered it via QR
200160 * code with an authenticator app.
201- *
202- * @returns {HTMLElement }
203161 */
204- renderValidateCodeScreen ( ) {
205- const { error, view } = this . state ;
206- const { TOTPVerifyComponent, onCompleteRegistration, errors } = this . props ;
207-
162+ function renderValidateCodeScreen ( ) {
208163 if ( view !== VIEWS . VALIDATE || errors . length ) {
209164 return null ;
210165 }
211-
212166 const verifyProps = {
213- ...this . props ,
167+ ...props ,
214168 // Override the error prop to come from the state instead of props
215- error,
216- moreOptionsControl : this . renderBackButtonForVerify ( ) ,
169+ error : stateError ,
170+ moreOptionsControl : renderBackButtonForVerify ( ) ,
217171 // Renaming registration callback so it fits in the Verify context
218172 onCompleteVerification : onCompleteRegistration ,
219- onCompleteRegistration : null ,
173+ onCompleteRegistration : null
220174 } ;
221-
222175 return < TOTPVerifyComponent { ...verifyProps } /> ;
223176 }
224177
225- render ( ) {
226- return (
227- < div className = "mfa-totp__container mfa-totp__container--register" >
228- { this . renderErrorScreen ( ) }
229- { this . renderScanCodeScreen ( ) }
230- { this . renderValidateCodeScreen ( ) }
231- </ div >
232- ) ;
233- }
178+ // Render the component
179+ return < div className = "mfa-totp__container mfa-totp__container--register" >
180+ { renderErrorScreen ( ) }
181+ { renderScanCodeScreen ( ) }
182+ { renderValidateCodeScreen ( ) }
183+ </ div > ;
234184}
235185
236186Register . propTypes = {
0 commit comments