@visns-studio/visns-components 6.3.16 → 6.3.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -91,7 +91,7 @@
|
|
|
91
91
|
"react-dom": "^17.0.0 || ^18.0.0"
|
|
92
92
|
},
|
|
93
93
|
"name": "@visns-studio/visns-components",
|
|
94
|
-
"version": "6.3.
|
|
94
|
+
"version": "6.3.18",
|
|
95
95
|
"description": "Various packages to assist in the development of our Custom Applications.",
|
|
96
96
|
"main": "src/index.js",
|
|
97
97
|
"files": [
|
|
@@ -239,7 +239,14 @@ function Notification(props) {
|
|
|
239
239
|
</button>
|
|
240
240
|
|
|
241
241
|
{show && (
|
|
242
|
-
<div
|
|
242
|
+
<div
|
|
243
|
+
className={styles.dropdownWrapper}
|
|
244
|
+
ref={wrapperRef}
|
|
245
|
+
/* Tells a scrollable host — the navigation's action pill —
|
|
246
|
+
to stop clipping while this is open. See
|
|
247
|
+
Navigation.module.scss `.hactions > ul`. */
|
|
248
|
+
data-nav-overlay="open"
|
|
249
|
+
>
|
|
243
250
|
<div className={styles.notibox}>
|
|
244
251
|
<div className={styles.notiboxHeader}>
|
|
245
252
|
<h3>Notifications</h3>
|
|
@@ -87,7 +87,9 @@ function SwitchAccount({ setSystemAuth, setting, userProfile }) {
|
|
|
87
87
|
</a>
|
|
88
88
|
|
|
89
89
|
{show && (
|
|
90
|
-
|
|
90
|
+
/* `data-nav-overlay` stops the navigation's scrollable action
|
|
91
|
+
pill from clipping this list. See Navigation.module.scss. */
|
|
92
|
+
<div ref={wrapperRef} data-nav-overlay="open">
|
|
91
93
|
{data.length > 0 ? (
|
|
92
94
|
<div className={styles.notibox}>
|
|
93
95
|
{data.map((item) => (
|
|
@@ -11,7 +11,18 @@ import CustomFetch from '../Fetch';
|
|
|
11
11
|
import TableFilter from '../TableFilter';
|
|
12
12
|
import styles from '../styles/Profile.module.scss';
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
/**
|
|
15
|
+
* One labelled control.
|
|
16
|
+
*
|
|
17
|
+
* The label used to be a `<span>` absolutely positioned inside the box, which
|
|
18
|
+
* is why this component carried two copies of the same `<input>`: the floating
|
|
19
|
+
* treatment needed the span after the input for text fields and before it for
|
|
20
|
+
* passwords, which start in the raised state. A label above the box needs
|
|
21
|
+
* neither trick, so there is one input, in one order, and it is addressable by
|
|
22
|
+
* a real `htmlFor`.
|
|
23
|
+
*
|
|
24
|
+
* Every prop, and the value each of them carries, is unchanged.
|
|
25
|
+
*/
|
|
15
26
|
const FormField = memo(
|
|
16
27
|
({
|
|
17
28
|
type = 'text',
|
|
@@ -23,39 +34,23 @@ const FormField = memo(
|
|
|
23
34
|
error = '',
|
|
24
35
|
children,
|
|
25
36
|
}) => {
|
|
26
|
-
const
|
|
37
|
+
const id = `profile-${name}`;
|
|
27
38
|
|
|
28
39
|
return (
|
|
29
40
|
<div className={styles.formItem}>
|
|
30
|
-
<label className={styles.
|
|
31
|
-
{
|
|
32
|
-
<input
|
|
33
|
-
type={type}
|
|
34
|
-
name={name}
|
|
35
|
-
onChange={onChange}
|
|
36
|
-
className={`${styles.input} ${error}`}
|
|
37
|
-
value={value}
|
|
38
|
-
readOnly={readOnly}
|
|
39
|
-
/>
|
|
40
|
-
)}
|
|
41
|
-
<span
|
|
42
|
-
className={`${styles.fi__span} ${
|
|
43
|
-
isPrefocused ? styles.prefocus : ''
|
|
44
|
-
}`}
|
|
45
|
-
>
|
|
46
|
-
{label}
|
|
47
|
-
</span>
|
|
48
|
-
{isPrefocused && (
|
|
49
|
-
<input
|
|
50
|
-
type={type}
|
|
51
|
-
name={name}
|
|
52
|
-
onChange={onChange}
|
|
53
|
-
value={value}
|
|
54
|
-
className={`${styles.input} ${error}`}
|
|
55
|
-
/>
|
|
56
|
-
)}
|
|
57
|
-
{children}
|
|
41
|
+
<label className={styles.fieldLabel} htmlFor={id}>
|
|
42
|
+
{label}
|
|
58
43
|
</label>
|
|
44
|
+
<input
|
|
45
|
+
id={id}
|
|
46
|
+
type={type}
|
|
47
|
+
name={name}
|
|
48
|
+
onChange={onChange}
|
|
49
|
+
className={`${styles.input} ${error}`}
|
|
50
|
+
value={value}
|
|
51
|
+
readOnly={readOnly}
|
|
52
|
+
/>
|
|
53
|
+
{children}
|
|
59
54
|
</div>
|
|
60
55
|
);
|
|
61
56
|
}
|
|
@@ -451,56 +446,143 @@ const Profile = ({ userProfile, setUserProfile }) => {
|
|
|
451
446
|
<div className={styles.gridtxt__header}>
|
|
452
447
|
<span>Overview</span>
|
|
453
448
|
</div>
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
449
|
+
{/* Three decisions, three sections, rather than one
|
|
450
|
+
flat run of fields: what the account is called,
|
|
451
|
+
whether to change the password, and what the
|
|
452
|
+
signature looks like. Each says what it is on the
|
|
453
|
+
left and carries only its own controls on the
|
|
454
|
+
right. */}
|
|
455
|
+
<form
|
|
456
|
+
className={styles.form}
|
|
457
|
+
onSubmit={handleSubmitProfile}
|
|
458
|
+
>
|
|
459
|
+
<section className={styles.section}>
|
|
460
|
+
<div className={styles.sectionAside}>
|
|
461
|
+
<h3 className={styles.sectionTitle}>
|
|
462
|
+
Account
|
|
463
|
+
</h3>
|
|
464
|
+
<p className={styles.sectionDescription}>
|
|
465
|
+
The name shown beside your work. Your
|
|
466
|
+
sign-in address is set by an
|
|
467
|
+
administrator and cannot be edited
|
|
468
|
+
here.
|
|
469
|
+
</p>
|
|
470
|
+
</div>
|
|
471
|
+
<div className={styles.sectionFields}>
|
|
472
|
+
<div className={styles.fieldPair}>
|
|
473
|
+
<FormField
|
|
474
|
+
name="name"
|
|
475
|
+
value={profile.name}
|
|
476
|
+
onChange={handleChangeProfile}
|
|
477
|
+
label="Name *"
|
|
478
|
+
error={inputClasses.name}
|
|
479
|
+
/>
|
|
480
|
+
|
|
481
|
+
<FormField
|
|
482
|
+
name="email"
|
|
483
|
+
value={profile.email}
|
|
484
|
+
readOnly={true}
|
|
485
|
+
label="Email *"
|
|
486
|
+
error={inputClasses.email}
|
|
487
|
+
/>
|
|
488
|
+
</div>
|
|
489
|
+
</div>
|
|
490
|
+
</section>
|
|
491
|
+
|
|
492
|
+
<section className={styles.section}>
|
|
493
|
+
<div className={styles.sectionAside}>
|
|
494
|
+
<h3 className={styles.sectionTitle}>
|
|
495
|
+
Change password
|
|
496
|
+
</h3>
|
|
497
|
+
<p className={styles.sectionDescription}>
|
|
498
|
+
Leave both fields blank to keep your
|
|
499
|
+
current password — nothing is sent
|
|
500
|
+
unless you type a new one.
|
|
501
|
+
</p>
|
|
502
|
+
</div>
|
|
503
|
+
<div className={styles.sectionFields}>
|
|
504
|
+
<div className={styles.fieldPair}>
|
|
505
|
+
<FormField
|
|
506
|
+
type="password"
|
|
507
|
+
name="password"
|
|
508
|
+
value={profile.password}
|
|
509
|
+
onChange={handleChangeProfile}
|
|
510
|
+
label="Password"
|
|
511
|
+
error={inputClasses.password}
|
|
501
512
|
>
|
|
502
|
-
|
|
503
|
-
|
|
513
|
+
{/* Only once there is something to
|
|
514
|
+
measure. Rendered
|
|
515
|
+
unconditionally it sat under an
|
|
516
|
+
empty password box reporting
|
|
517
|
+
"too short" before the user had
|
|
518
|
+
typed a character. */}
|
|
519
|
+
{profile.password ? (
|
|
520
|
+
<PasswordStrengthBar
|
|
521
|
+
password={profile.password}
|
|
522
|
+
className={
|
|
523
|
+
styles.strengthMeter
|
|
524
|
+
}
|
|
525
|
+
scoreWordClassName={
|
|
526
|
+
styles.strengthWord
|
|
527
|
+
}
|
|
528
|
+
/>
|
|
529
|
+
) : null}
|
|
530
|
+
</FormField>
|
|
531
|
+
|
|
532
|
+
<FormField
|
|
533
|
+
type="password"
|
|
534
|
+
name="password_confirmation"
|
|
535
|
+
value={
|
|
536
|
+
profile.password_confirmation
|
|
537
|
+
}
|
|
538
|
+
onChange={handleChangeProfile}
|
|
539
|
+
label="Password Confirmation"
|
|
540
|
+
error={
|
|
541
|
+
inputClasses.password_confirmation
|
|
542
|
+
}
|
|
543
|
+
/>
|
|
544
|
+
</div>
|
|
545
|
+
</div>
|
|
546
|
+
</section>
|
|
547
|
+
|
|
548
|
+
<section className={styles.section}>
|
|
549
|
+
<div className={styles.sectionAside}>
|
|
550
|
+
<h3 className={styles.sectionTitle}>
|
|
551
|
+
Signature
|
|
552
|
+
</h3>
|
|
553
|
+
<p className={styles.sectionDescription}>
|
|
554
|
+
Applied to the documents generated for
|
|
555
|
+
you. Drawing a new one replaces the
|
|
556
|
+
signature held on your account when you
|
|
557
|
+
save.
|
|
558
|
+
</p>
|
|
559
|
+
</div>
|
|
560
|
+
<div className={styles.sectionFields}>
|
|
561
|
+
<div className={styles.signatureField}>
|
|
562
|
+
{/* Clear belongs to the pad, not to
|
|
563
|
+
the page: it sits on the caption's
|
|
564
|
+
line, quiet and small, instead of
|
|
565
|
+
standing beside Save at the bottom
|
|
566
|
+
of the screen. */}
|
|
567
|
+
<div
|
|
568
|
+
className={styles.signatureHeader}
|
|
569
|
+
>
|
|
570
|
+
<span
|
|
571
|
+
className={
|
|
572
|
+
styles.signatureCaption
|
|
573
|
+
}
|
|
574
|
+
>
|
|
575
|
+
Draw your signature
|
|
576
|
+
</span>
|
|
577
|
+
<button
|
|
578
|
+
className={styles.btnQuiet}
|
|
579
|
+
onClick={handleClearSignature}
|
|
580
|
+
disabled={isLoading}
|
|
581
|
+
type="button"
|
|
582
|
+
>
|
|
583
|
+
Clear
|
|
584
|
+
</button>
|
|
585
|
+
</div>
|
|
504
586
|
<div
|
|
505
587
|
className={
|
|
506
588
|
styles.signaturePadWrapper
|
|
@@ -508,6 +590,27 @@ const Profile = ({ userProfile, setUserProfile }) => {
|
|
|
508
590
|
>
|
|
509
591
|
<SignaturePad
|
|
510
592
|
ref={signatureRef}
|
|
593
|
+
/* Do not lower this, and do
|
|
594
|
+
not narrow
|
|
595
|
+
`--profile-signature-width`
|
|
596
|
+
either. The effect below
|
|
597
|
+
loads the stored signature
|
|
598
|
+
into the pad on mount, so
|
|
599
|
+
the pad is non-empty on an
|
|
600
|
+
ordinary save that never
|
|
601
|
+
touched it, and
|
|
602
|
+
`handleSubmitProfile` then
|
|
603
|
+
re-exports the canvas with
|
|
604
|
+
`toDataURL()` at whatever
|
|
605
|
+
size the canvas currently
|
|
606
|
+
is. A smaller pad therefore
|
|
607
|
+
writes a signature cropped
|
|
608
|
+
to the new geometry back to
|
|
609
|
+
the server — silently, on a
|
|
610
|
+
save the user made for some
|
|
611
|
+
other reason. Growing it is
|
|
612
|
+
safe; shrinking it destroys
|
|
613
|
+
ink. */
|
|
511
614
|
height={200}
|
|
512
615
|
options={{
|
|
513
616
|
penColor: 'black',
|
|
@@ -516,30 +619,33 @@ const Profile = ({ userProfile, setUserProfile }) => {
|
|
|
516
619
|
}}
|
|
517
620
|
redrawOnResize
|
|
518
621
|
canvasProps={{
|
|
622
|
+
/* The frame is on the
|
|
623
|
+
wrapper. A border or
|
|
624
|
+
padding on the canvas
|
|
625
|
+
itself sits inside the
|
|
626
|
+
bounding rect
|
|
627
|
+
signature_pad measures
|
|
628
|
+
against and outside the
|
|
629
|
+
drawing surface, which
|
|
630
|
+
offsets every stroke by
|
|
631
|
+
exactly that much. */
|
|
519
632
|
style: {
|
|
520
|
-
border: '2px solid #ccc',
|
|
521
|
-
borderRadius: '10px',
|
|
522
|
-
padding: '10px',
|
|
523
633
|
width: '100%',
|
|
524
634
|
},
|
|
525
635
|
className: styles.sigcanvas,
|
|
526
636
|
}}
|
|
527
637
|
/>
|
|
528
|
-
<small
|
|
529
|
-
style={{
|
|
530
|
-
display: 'block',
|
|
531
|
-
marginTop: '5px',
|
|
532
|
-
color: '#666',
|
|
533
|
-
}}
|
|
534
|
-
>
|
|
535
|
-
Draw your signature above
|
|
536
|
-
</small>
|
|
537
638
|
</div>
|
|
538
|
-
</
|
|
639
|
+
</div>
|
|
539
640
|
</div>
|
|
540
|
-
</
|
|
541
|
-
</
|
|
542
|
-
|
|
641
|
+
</section>
|
|
642
|
+
</form>
|
|
643
|
+
|
|
644
|
+
{/* The panel's footer. Save stands alone now that
|
|
645
|
+
Clear lives with the pad it clears. It stays
|
|
646
|
+
outside the `<form>`, where it has always been — a
|
|
647
|
+
submit button inside it would fire
|
|
648
|
+
`handleSubmitProfile` twice. */}
|
|
543
649
|
<div className={styles.polActions}>
|
|
544
650
|
<button
|
|
545
651
|
className={`${styles.btn} ${
|
|
@@ -551,14 +657,6 @@ const Profile = ({ userProfile, setUserProfile }) => {
|
|
|
551
657
|
>
|
|
552
658
|
{isLoading ? 'Saving...' : 'Save'}
|
|
553
659
|
</button>
|
|
554
|
-
<button
|
|
555
|
-
className={styles.btn}
|
|
556
|
-
onClick={handleClearSignature}
|
|
557
|
-
disabled={isLoading}
|
|
558
|
-
type="button"
|
|
559
|
-
>
|
|
560
|
-
Clear Signature
|
|
561
|
-
</button>
|
|
562
660
|
</div>
|
|
563
661
|
</div>
|
|
564
662
|
);
|
|
@@ -568,66 +666,97 @@ const Profile = ({ userProfile, setUserProfile }) => {
|
|
|
568
666
|
<div className={styles.gridtxt__header}>
|
|
569
667
|
<span>Two-Factor Authentication</span>
|
|
570
668
|
</div>
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
<span
|
|
581
|
-
className={styles.statusEnabled}
|
|
582
|
-
>
|
|
583
|
-
Enabled
|
|
584
|
-
</span>
|
|
585
|
-
) : (
|
|
586
|
-
<span
|
|
587
|
-
className={
|
|
588
|
-
styles.statusDisabled
|
|
589
|
-
}
|
|
590
|
-
>
|
|
591
|
-
Disabled
|
|
592
|
-
</span>
|
|
593
|
-
)}
|
|
669
|
+
{/* Same sectioning as Overview, so the two tabs read
|
|
670
|
+
as one screen: what 2FA is on the left, the state
|
|
671
|
+
of it and the control that changes that state on
|
|
672
|
+
the right. */}
|
|
673
|
+
<div className={styles.form}>
|
|
674
|
+
<section className={styles.section}>
|
|
675
|
+
<div className={styles.sectionAside}>
|
|
676
|
+
<h3 className={styles.sectionTitle}>
|
|
677
|
+
Authenticator app
|
|
594
678
|
</h3>
|
|
595
|
-
<p>
|
|
679
|
+
<p className={styles.sectionDescription}>
|
|
596
680
|
Two-factor authentication adds an extra
|
|
597
681
|
layer of security to your account. When
|
|
598
682
|
enabled, you'll need to provide both
|
|
599
683
|
your password and a verification code
|
|
600
|
-
from your authenticator app when
|
|
601
|
-
in.
|
|
684
|
+
from your authenticator app when
|
|
685
|
+
signing in.
|
|
602
686
|
</p>
|
|
687
|
+
</div>
|
|
688
|
+
<div className={styles.sectionFields}>
|
|
689
|
+
<div className={styles.twoFactorStatus}>
|
|
690
|
+
<h4>
|
|
691
|
+
Status:{' '}
|
|
692
|
+
{twoFactorEnabled ? (
|
|
693
|
+
<span
|
|
694
|
+
className={
|
|
695
|
+
styles.statusEnabled
|
|
696
|
+
}
|
|
697
|
+
>
|
|
698
|
+
Enabled
|
|
699
|
+
</span>
|
|
700
|
+
) : (
|
|
701
|
+
<span
|
|
702
|
+
className={
|
|
703
|
+
styles.statusDisabled
|
|
704
|
+
}
|
|
705
|
+
>
|
|
706
|
+
Disabled
|
|
707
|
+
</span>
|
|
708
|
+
)}
|
|
709
|
+
</h4>
|
|
603
710
|
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
711
|
+
{!twoFactorEnabled &&
|
|
712
|
+
!showTwoFactorSetup && (
|
|
713
|
+
<button
|
|
714
|
+
className={`${styles.btn} ${styles.btnPrimary}`}
|
|
715
|
+
onClick={
|
|
716
|
+
fetchTwoFactorSetupData
|
|
717
|
+
}
|
|
718
|
+
disabled={isLoading}
|
|
719
|
+
>
|
|
720
|
+
{isLoading
|
|
721
|
+
? 'Loading...'
|
|
722
|
+
: 'Set up two-factor authentication'}
|
|
723
|
+
</button>
|
|
724
|
+
)}
|
|
618
725
|
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
<p
|
|
726
|
+
{twoFactorEnabled &&
|
|
727
|
+
userProfile.two_factor_confirmed_at && (
|
|
728
|
+
<div
|
|
623
729
|
className={
|
|
624
|
-
styles.
|
|
730
|
+
styles.statusActions
|
|
625
731
|
}
|
|
626
732
|
>
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
733
|
+
<p
|
|
734
|
+
className={
|
|
735
|
+
styles.confirmedMessage
|
|
736
|
+
}
|
|
737
|
+
>
|
|
738
|
+
Two-factor
|
|
739
|
+
authentication is set up
|
|
740
|
+
and confirmed. Your
|
|
741
|
+
account is now more
|
|
742
|
+
secure.
|
|
743
|
+
</p>
|
|
744
|
+
<button
|
|
745
|
+
className={`${styles.btn} ${styles.btnDanger}`}
|
|
746
|
+
onClick={
|
|
747
|
+
disableTwoFactor
|
|
748
|
+
}
|
|
749
|
+
disabled={isLoading}
|
|
750
|
+
>
|
|
751
|
+
{isLoading
|
|
752
|
+
? 'Disabling...'
|
|
753
|
+
: 'Disable two-factor authentication'}
|
|
754
|
+
</button>
|
|
755
|
+
</div>
|
|
756
|
+
)}
|
|
757
|
+
|
|
758
|
+
{twoFactorEnabled &&
|
|
759
|
+
!userProfile.two_factor_confirmed_at && (
|
|
631
760
|
<button
|
|
632
761
|
className={`${styles.btn} ${styles.btnDanger}`}
|
|
633
762
|
onClick={disableTwoFactor}
|
|
@@ -637,29 +766,30 @@ const Profile = ({ userProfile, setUserProfile }) => {
|
|
|
637
766
|
? 'Disabling...'
|
|
638
767
|
: 'Disable two-factor authentication'}
|
|
639
768
|
</button>
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
{twoFactorEnabled &&
|
|
644
|
-
!userProfile.two_factor_confirmed_at && (
|
|
645
|
-
<button
|
|
646
|
-
className={`${styles.btn} ${styles.btnDanger}`}
|
|
647
|
-
onClick={disableTwoFactor}
|
|
648
|
-
disabled={isLoading}
|
|
649
|
-
>
|
|
650
|
-
{isLoading
|
|
651
|
-
? 'Disabling...'
|
|
652
|
-
: 'Disable two-factor authentication'}
|
|
653
|
-
</button>
|
|
654
|
-
)}
|
|
769
|
+
)}
|
|
770
|
+
</div>
|
|
655
771
|
</div>
|
|
772
|
+
</section>
|
|
656
773
|
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
774
|
+
{showTwoFactorSetup && (
|
|
775
|
+
<section className={styles.section}>
|
|
776
|
+
<div className={styles.sectionAside}>
|
|
777
|
+
<h3 className={styles.sectionTitle}>
|
|
660
778
|
Set up two-factor authentication
|
|
661
779
|
</h3>
|
|
662
|
-
<
|
|
780
|
+
<p
|
|
781
|
+
className={
|
|
782
|
+
styles.sectionDescription
|
|
783
|
+
}
|
|
784
|
+
>
|
|
785
|
+
Pair an app with your account, then
|
|
786
|
+
confirm the pairing with a code from
|
|
787
|
+
it. Keep the recovery codes.
|
|
788
|
+
</p>
|
|
789
|
+
</div>
|
|
790
|
+
<div className={styles.sectionFields}>
|
|
791
|
+
<div className={styles.twoFactorSetup}>
|
|
792
|
+
<ol className={styles.setupSteps}>
|
|
663
793
|
<li>
|
|
664
794
|
<p>
|
|
665
795
|
Install an authenticator app
|
|
@@ -892,22 +1022,27 @@ const Profile = ({ userProfile, setUserProfile }) => {
|
|
|
892
1022
|
device.
|
|
893
1023
|
</p>
|
|
894
1024
|
</li>
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
className={`${styles.btn} ${styles.btnSecondary}`}
|
|
899
|
-
onClick={() =>
|
|
900
|
-
setShowTwoFactorSetup(false)
|
|
901
|
-
}
|
|
902
|
-
type="button"
|
|
903
|
-
disabled={isLoading}
|
|
1025
|
+
</ol>
|
|
1026
|
+
<div
|
|
1027
|
+
className={styles.setupActions}
|
|
904
1028
|
>
|
|
905
|
-
|
|
906
|
-
|
|
1029
|
+
<button
|
|
1030
|
+
className={`${styles.btn} ${styles.btnSecondary}`}
|
|
1031
|
+
onClick={() =>
|
|
1032
|
+
setShowTwoFactorSetup(
|
|
1033
|
+
false
|
|
1034
|
+
)
|
|
1035
|
+
}
|
|
1036
|
+
type="button"
|
|
1037
|
+
disabled={isLoading}
|
|
1038
|
+
>
|
|
1039
|
+
Cancel
|
|
1040
|
+
</button>
|
|
1041
|
+
</div>
|
|
907
1042
|
</div>
|
|
908
1043
|
</div>
|
|
909
|
-
|
|
910
|
-
|
|
1044
|
+
</section>
|
|
1045
|
+
)}
|
|
911
1046
|
</div>
|
|
912
1047
|
</div>
|
|
913
1048
|
);
|