Skip to content

Commit

Permalink
Wallet settings, change password and download mnemonic (Joystream#4326)
Browse files Browse the repository at this point in the history
* wip

* settings view ground work

* uncomment route

* add borderColor prop to banner

* fix issues with modal paddings

* create password form component, sign up modal refactoring

* add export seed dialog and change password dialog

* handle copy button

* show different settings for wallet users

* refactor password dialogs

* cr fixes

* Update packages/atlas/src/views/viewer/MembershipSettingsView/MembershipWallet/MembershipWallet.tsx

Co-authored-by: attemka <attemka@gmail.com>

* auth helpers further refactor

* reset form on cancel

* cr fixes

* cr fixes 2

* add additional step to ChangePassword

* action bar adjustments, add unsaved changes dialog

* fix viewer layout

* action bar changes

* action bar adjustments

* cr fixes

* fix fee issue

* change password fix?

---------

Co-authored-by: attemka <attemka@gmail.com>
  • Loading branch information
2 people authored and Artem committed Jul 5, 2023
1 parent 99ba39e commit 7135913
Show file tree
Hide file tree
Showing 36 changed files with 1,005 additions and 181 deletions.
29 changes: 15 additions & 14 deletions packages/atlas/src/components/ActionBar/ActionBar.styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,20 +47,6 @@ export const StyledInformation = styled(Information)`
margin-left: ${sizes(1)};
`

export const ActionButtonPrimary = styled(Button)<{ secondaryButtonExists: boolean }>`
grid-area: primary-button;
${({ secondaryButtonExists }) =>
!secondaryButtonExists &&
css`
grid-column: 1 / span 2;
${media.sm} {
grid-column: -3 / span 2;
}
`}
`

export const SecondaryButton = styled(Button)`
grid-area: secondary-button;
`
Expand All @@ -80,3 +66,18 @@ export const FeeContainer = styled.div`
display: flex;
align-items: center;
`

export const PrimaryButtonContainer = styled.div<{ secondaryButtonExists: boolean }>`
grid-area: primary-button;
width: 100%;
${({ secondaryButtonExists }) =>
!secondaryButtonExists &&
css`
grid-column: 1 / span 2;
${media.sm} {
grid-column: -3 / span 2;
}
`}
`
32 changes: 18 additions & 14 deletions packages/atlas/src/components/ActionBar/ActionBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,16 @@ import { CSSTransition } from 'react-transition-group'
import { Fee } from '@/components/Fee'
import { Text } from '@/components/Text'
import { Tooltip, TooltipProps } from '@/components/Tooltip'
import { ButtonProps } from '@/components/_buttons/Button'
import { Button, ButtonProps } from '@/components/_buttons/Button'
import { useHasEnoughBalance } from '@/hooks/useHasEnoughBalance'
import { useMediaMatch } from '@/hooks/useMediaMatch'
import { transitions } from '@/styles'

import {
ActionBarContainer,
ActionButtonPrimary,
DraftsBadgeContainer,
FeeContainer,
PrimaryButtonContainer,
SecondaryButton,
StyledInformation,
} from './ActionBar.styles'
Expand Down Expand Up @@ -93,18 +93,22 @@ export const ActionBar = forwardRef<HTMLDivElement, ActionBarProps>(
{secondaryButton?.text}
</SecondaryButton>
</CSSTransition>
<ActionButtonPrimary
{...primaryButton}
ref={buttonRef}
disabled={primaryButton.disabled || loadingState}
onClick={isNoneCrypto ? primaryButton.onClick : signTransactionHandler}
secondaryButtonExists={!!secondaryButton}
size={smMatch ? 'large' : 'medium'}
type="submit"
>
{loadingState ? 'Please wait...' : primaryButton.text}
</ActionButtonPrimary>
{primaryButtonTooltip && <Tooltip reference={buttonRef.current} {...primaryButtonTooltip} />}
<PrimaryButtonContainer secondaryButtonExists={!!secondaryButton}>
{/* tooltip is positioned weirdly on this button, that's we are setting offsetY to 22 */}
<Tooltip offsetY={22} {...primaryButtonTooltip}>
<Button
fullWidth
{...primaryButton}
ref={buttonRef}
disabled={primaryButton.disabled || loadingState}
onClick={isNoneCrypto ? primaryButton.onClick : signTransactionHandler}
size={smMatch ? 'large' : 'medium'}
type="submit"
>
{loadingState ? 'Please wait...' : primaryButton.text}
</Button>
</Tooltip>
</PrimaryButtonContainer>
</ActionBarContainer>
)
}
Expand Down
4 changes: 2 additions & 2 deletions packages/atlas/src/components/Banner/Banner.styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,13 @@ export const BannerDescription = styled.div<{ withTitle?: boolean }>`
white-space: pre-line;
`

export const BannerWrapper = styled.div<{ size: 'small' | 'medium' }>`
export const BannerWrapper = styled.div<{ size: 'small' | 'medium'; borderColor?: string }>`
flex: 1;
position: relative;
padding: ${(props) => (props.size === 'small' ? sizes(4) : sizes(6))};
width: 100%;
background-color: ${cVar('colorBackgroundMutedAlpha')};
border-left: 2px solid ${cVar('colorBorderPrimary')};
border-left: 2px solid ${({ borderColor }) => borderColor ?? cVar('colorBorderPrimary')};
`

export const ActionButton = styled(Button)`
Expand Down
4 changes: 3 additions & 1 deletion packages/atlas/src/components/Banner/Banner.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ type ActionButtonProps = {

export type BannerProps = {
dismissibleId?: string
borderColor?: string
title?: string
description?: ReactNode
className?: string
Expand All @@ -32,6 +33,7 @@ export type BannerProps = {

export const Banner: FC<BannerProps> = ({
title,
borderColor,
description,
className,
icon,
Expand All @@ -49,7 +51,7 @@ export const Banner: FC<BannerProps> = ({
}

return (
<BannerWrapper size={size} className={className}>
<BannerWrapper size={size} className={className} borderColor={borderColor}>
<Container>
<div>
{title && (
Expand Down
11 changes: 9 additions & 2 deletions packages/atlas/src/components/PageTabs/PageTabs.styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,15 @@ export const PageTabsWrapper = styled.div`
padding: 0 ${sizes(4)};
box-shadow: ${cVar('effectDividersBottom')};
display: flex;
justify-content: space-between;
`

export const BackActionWrapper = styled.div`
display: flex;
align-items: center;
padding: ${sizes(2)} ${sizes(4)} ${sizes(2)} 0;
position: relative;
border-right: 1px solid ${cVar('colorCoreNeutral600')};
`
export const TailingContentWrapper = styled.div`
margin: ${sizes(2)} ${sizes(4)};
margin: ${sizes(2)} ${sizes(4)} ${sizes(2)} auto;
`
21 changes: 16 additions & 5 deletions packages/atlas/src/components/PageTabs/PageTabs.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,30 @@
import { FC, ReactNode } from 'react'

import { PageTabsWrapper, TailingContentWrapper } from './PageTabs.styles'
import { SvgActionChevronL } from '@/assets/icons'

import { BackActionWrapper, PageTabsWrapper, TailingContentWrapper } from './PageTabs.styles'

import { Tabs, TabsProps } from '../Tabs'
import { Button, ButtonProps } from '../_buttons/Button'

type BackAction = Pick<ButtonProps, 'to' | 'onClick'>

type PageTabsProps = {
type PageTabsProps = Omit<TabsProps, 'underline'> & {
backAction?: BackAction
trailingContent?: ReactNode
} & Omit<TabsProps, 'underline'>
}

export const PageTabs: FC<PageTabsProps> = ({ className, trailingContent, ...tabsProps }) => {
export const PageTabs: FC<PageTabsProps> = ({ className, backAction, trailingContent, ...tabsProps }) => {
return (
<PageTabsWrapper className={className}>
{backAction && (
<BackActionWrapper>
<Button variant="tertiary" size="medium" icon={<SvgActionChevronL />} {...backAction} />
</BackActionWrapper>
)}
<Tabs {...tabsProps} />
{/* todo add support for filters */}
{trailingContent && <TailingContentWrapper>{trailingContent}</TailingContentWrapper>}
{/* todo add support for filters */}
</PageTabsWrapper>
)
}
4 changes: 2 additions & 2 deletions packages/atlas/src/components/Tooltip/Tooltip.styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ type TooltipTextProps = {

export const TooltipText = styled(Text)<TooltipTextProps>`
display: inline-block;
max-width: 200px;
max-width: 224px;
${({ withIcon, headerText }) => withIcon && headerText && `margin-left: ${sizes(7)}`};
`
Expand All @@ -48,7 +48,7 @@ const customContentCss = css`
`

export const TooltipContainer = styled.div<TooltipContainerProps>`
display: inline-flex;
display: block;
flex-direction: ${({ hasHeader, hasCustomContent }) => (hasHeader || hasCustomContent ? 'column' : 'row')};
padding: ${({ hasHeader, multiline }) => sizes(hasHeader || multiline ? 3 : 2)};
background-color: ${cVar('colorBackgroundElevated')};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ import { Button } from '@/components/_buttons/Button'
import { DialogModal } from '@/components/_overlays/DialogModal'
import { atlasConfig } from '@/config'
import { ORION_AUTH_URL } from '@/config/env'
import { keyring, loginRequest, logoutRequest, prepareEncryptionArtifacts } from '@/providers/auth/auth.helpers'
import { keyring } from '@/joystream-lib/lib'
import { loginRequest, logoutRequest, prepareEncryptionArtifacts } from '@/providers/auth/auth.helpers'
import { useAuthStore } from '@/providers/auth/auth.store'
import { useSnackbar } from '@/providers/snackbars'
import { SentryLogger } from '@/utils/logs'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ export const PasswordRequirementsList = styled.ul`
list-style-type: none;
display: grid;
gap: ${sizes(2)};
margin-bottom: ${sizes(6)};
`

export const PasswordRequirementItem = styled(Text)`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,11 @@ export const PasswordCriteria: FC<PasswordCriteriaProps> = ({ text, validationSt
)
}

export const PasswordCriterias = ({ path = 'password' }: { path?: string }) => {
type PasswordCriteriasProps = {
path?: string
}

export const PasswordCriterias: FC<PasswordCriteriasProps> = ({ path = 'password' }) => {
const context = useFormContext()
const [passwordRequirementsErrors, setPasswordRequirementsErrors] = useState<PasswordRequirementsErrors>(
PASSWORD_REQUIREMENTS_ERRORS_INITIAL_STATE
Expand All @@ -91,7 +95,7 @@ export const PasswordCriterias = ({ path = 'password' }: { path?: string }) => {
}

setPasswordRequirementsErrors(() => ({
length: getValidationState(password.length <= 9),
length: getValidationState(password.length <= 9 || password.length >= 64),
number: getValidationState(/^[^0-9]*$/.test(password)),
upperCase: getValidationState(/^[^A-Z]*$/.test(password)),
specialCharacter: getValidationState(/^[^!@#$%^&*()_+]*$/.test(password)),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ export const SignUpModal = () => {
{currentStep === SignUpSteps.SignUpEmail && (
<SignUpEmailStep
{...commonProps}
isOverflowing={overflow || !smMatch}
isEmailAlreadyTakenError={emailAlreadyTakenError}
onEmailSubmit={handleEmailStepSubmit}
email={signUpFormData.email}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,15 @@ type EmailStepForm = z.infer<typeof zodSchema>
type SignUpEmailStepProps = {
onEmailSubmit: (email: string, confirmedTerms: boolean) => void
isEmailAlreadyTakenError?: boolean
isOverflowing: boolean
} & SignUpStepsCommonProps &
Pick<AccountFormData, 'email' | 'confirmedTerms'>

export const SignUpEmailStep: FC<SignUpEmailStepProps> = ({
setPrimaryButtonProps,
hasNavigatedBack,
isEmailAlreadyTakenError,
isOverflowing,
onEmailSubmit,
confirmedTerms,
email,
Expand Down Expand Up @@ -94,7 +96,7 @@ export const SignUpEmailStep: FC<SignUpEmailStepProps> = ({
hasNavigatedBack={hasNavigatedBack}
subtitle="If you misspell your email address, please note that there is no option for us to recover your account."
>
<StyledSignUpForm>
<StyledSignUpForm additionalPaddingBottom={!isOverflowing}>
<FormField label="Email" error={errors.email?.message}>
<Input {...register('email')} placeholder="Email" error={!!errors.email} />
</FormField>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,38 +1,18 @@
import { zodResolver } from '@hookform/resolvers/zod'
import { FC, RefObject, useCallback, useEffect, useRef, useState } from 'react'
import { FormProvider, useForm } from 'react-hook-form'
import { z } from 'zod'

import { SvgActionHide, SvgActionShow } from '@/assets/icons'
import { AuthenticationModalStepTemplate } from '@/components/_auth/AuthenticationModalStepTemplate'
import { PasswordCriterias } from '@/components/_auth/PasswordCriterias'
import { FormField } from '@/components/_inputs/FormField'
import { Input, InputProps } from '@/components/_inputs/Input'
import { AccountFormData } from '@/hooks/useCreateMember'
import { passwordAndRepeatPasswordSchema } from '@/utils/formValidationOptions'

import { StyledSignUpForm } from '../SignUpSteps.styles'
import { SignUpStepsCommonProps } from '../SignUpSteps.types'

const commonPasswordValidation = z
.string()
.regex(/^(?=.*[0-9])(?=.*[A-Z])(?=.*[!@#$%^&*()_+]).*$/, { message: 'Password has to meet requirements.' })
.min(9, { message: 'Password has to meet requirements.' })

const zodSchema = z
.object({
password: commonPasswordValidation,
confirmPassword: commonPasswordValidation,
})
.refine(
(data) => {
return data.password === data.confirmPassword
},
{
path: ['confirmPassword'],
message: 'Password address has to match.',
}
)

type PasswordStepForm = {
password: string
confirmPassword: string
Expand All @@ -59,7 +39,7 @@ export const SignUpPasswordStep: FC<SignUpPasswordStepProps> = ({
password,
confirmPassword: password,
},
resolver: zodResolver(zodSchema),
resolver: zodResolver(passwordAndRepeatPasswordSchema),
})
const {
handleSubmit,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ import styled from '@emotion/styled'

import { cVar, sizes } from '@/styles'

export const StyledSignUpForm = styled.form`
export const StyledSignUpForm = styled.form<{ additionalPaddingBottom?: boolean }>`
display: grid;
gap: ${sizes(6)};
padding-bottom: ${({ additionalPaddingBottom }) =>
additionalPaddingBottom ? 'var(--local-size-dialog-padding)' : 0};
`

export const CheckboxWrapper = styled.div<{ isAccepted: boolean }>`
Expand Down
5 changes: 3 additions & 2 deletions packages/atlas/src/components/_inputs/Input/Input.styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
type TextInputProps = {
error?: boolean
inputSize: InputSize
disabledAttributeOnly?: boolean
} & NodeWidthProps

export const TextInput = styled.input<TextInputProps>`
Expand Down Expand Up @@ -83,7 +84,7 @@ export const NodeContainer = styled.div<NodeContainerProps>`
${nodePlacementStyles};
`

export const InputContainer = styled.div<{ size: InputSize }>`
export const InputContainer = styled.div<{ size: InputSize; ignoreBoxShadow?: boolean }>`
position: relative;
height: max-content;
font: ${({ size }) => (size === 'large' ? cVar('typographyDesktopT300') : cVar('typographyDesktopT200'))};
Expand All @@ -92,7 +93,7 @@ export const InputContainer = styled.div<{ size: InputSize }>`
:focus-within {
${TextInput} {
${getSharedInputStyles().focus};
${({ ignoreBoxShadow }) => getSharedInputStyles(ignoreBoxShadow).focus};
}
${NodeContainer} {
> svg > path {
Expand Down
Loading

0 comments on commit 7135913

Please sign in to comment.