mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2024-11-28 21:44:06 -05:00
refactor(frontend): deduplicated username field
Signed-off-by: Avinash <avinash.kumar.cs92@gmail.com>
This commit is contained in:
parent
d0036e1a80
commit
6babc8997c
6 changed files with 63 additions and 72 deletions
|
@ -4,42 +4,38 @@
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
import type { CommonFieldProps } from './fields'
|
import type { CommonFieldProps } from './fields'
|
||||||
import React, { useMemo } from 'react'
|
import React from 'react'
|
||||||
import { Form } from 'react-bootstrap'
|
import { Form } from 'react-bootstrap'
|
||||||
import { Trans, useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
|
|
||||||
|
export interface UsernameFieldProps extends CommonFieldProps {
|
||||||
|
isInvalid?: boolean
|
||||||
|
isValid?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renders an input field for the username when registering.
|
* Renders an input field for the username when registering.
|
||||||
*
|
*
|
||||||
* @param onChange Hook that is called when the entered username changes.
|
* @param onChange Callback that is called when the entered username changes.
|
||||||
* @param value The currently entered username.
|
* @param value The currently entered username.
|
||||||
|
* @param isValid Is a valid field or not
|
||||||
|
* @param isInvalid Adds error style to label
|
||||||
*/
|
*/
|
||||||
export const UsernameField: React.FC<CommonFieldProps> = ({ onChange, value }) => {
|
export const UsernameField: React.FC<UsernameFieldProps> = ({ onChange, value, isValid, isInvalid }) => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
|
|
||||||
const isValid = useMemo(() => {
|
|
||||||
return value?.trim() !== ''
|
|
||||||
}, [value])
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form.Group>
|
<Form.Control
|
||||||
<Form.Label>
|
type='text'
|
||||||
<Trans i18nKey='login.auth.username' />
|
size='sm'
|
||||||
</Form.Label>
|
value={value}
|
||||||
<Form.Control
|
isValid={isValid}
|
||||||
type='text'
|
isInvalid={isInvalid}
|
||||||
size='sm'
|
onChange={onChange}
|
||||||
value={value}
|
placeholder={t('login.auth.username') ?? undefined}
|
||||||
isValid={isValid}
|
autoComplete='username'
|
||||||
onChange={onChange}
|
autoFocus={true}
|
||||||
placeholder={t('login.auth.username') ?? undefined}
|
required
|
||||||
autoComplete='username'
|
/>
|
||||||
autoFocus={true}
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
<Form.Text>
|
|
||||||
<Trans i18nKey='login.register.usernameInfo' />
|
|
||||||
</Form.Text>
|
|
||||||
</Form.Group>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
import { UsernameField } from './username-field'
|
||||||
|
import type { UsernameFieldProps } from './username-field'
|
||||||
|
import React from 'react'
|
||||||
|
import { Form } from 'react-bootstrap'
|
||||||
|
import { Trans } from 'react-i18next'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wraps and contains label and info for UsernameField
|
||||||
|
*
|
||||||
|
* @param onChange Callback that is called when the entered username changes.
|
||||||
|
* @param value The currently entered username.
|
||||||
|
* @param isValid Is a valid field or not
|
||||||
|
* @param isInvalid Adds error style to label
|
||||||
|
*/
|
||||||
|
export const UsernameLabelField: React.FC<UsernameFieldProps> = (props) => {
|
||||||
|
return (
|
||||||
|
<Form.Group>
|
||||||
|
<Form.Label>
|
||||||
|
<Trans i18nKey='login.auth.username' />
|
||||||
|
</Form.Label>
|
||||||
|
<UsernameField {...props} />
|
||||||
|
<Form.Text>
|
||||||
|
<Trans i18nKey='login.register.usernameInfo' />
|
||||||
|
</Form.Text>
|
||||||
|
</Form.Group>
|
||||||
|
)
|
||||||
|
}
|
|
@ -1,39 +0,0 @@
|
||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
|
||||||
*/
|
|
||||||
import type { AuthFieldProps } from './fields'
|
|
||||||
import React from 'react'
|
|
||||||
import { Form } from 'react-bootstrap'
|
|
||||||
import { useTranslation } from 'react-i18next'
|
|
||||||
|
|
||||||
export interface UsernameFieldProps extends AuthFieldProps {
|
|
||||||
value: string
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO: This should be replaced with the common username component. See https://github.com/hedgedoc/hedgedoc/issues/4128
|
|
||||||
/**
|
|
||||||
* Renders an input field for a username.
|
|
||||||
*
|
|
||||||
* @param onChange Hook that is called when the input is changed.
|
|
||||||
* @param invalid True indicates that the username is invalid, false otherwise.
|
|
||||||
* @param value the username value
|
|
||||||
*/
|
|
||||||
export const UsernameField: React.FC<UsernameFieldProps> = ({ onChange, invalid, value }) => {
|
|
||||||
const { t } = useTranslation()
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Form.Group>
|
|
||||||
<Form.Control
|
|
||||||
isInvalid={invalid}
|
|
||||||
value={value}
|
|
||||||
type='text'
|
|
||||||
size='sm'
|
|
||||||
placeholder={t('login.auth.username') ?? undefined}
|
|
||||||
onChange={onChange}
|
|
||||||
autoComplete='username'
|
|
||||||
/>
|
|
||||||
</Form.Group>
|
|
||||||
)
|
|
||||||
}
|
|
|
@ -6,8 +6,8 @@
|
||||||
import { doLdapLogin } from '../../../api/auth/ldap'
|
import { doLdapLogin } from '../../../api/auth/ldap'
|
||||||
import { useLowercaseOnInputChange } from '../../../hooks/common/use-lowercase-on-input-change'
|
import { useLowercaseOnInputChange } from '../../../hooks/common/use-lowercase-on-input-change'
|
||||||
import { useOnInputChange } from '../../../hooks/common/use-on-input-change'
|
import { useOnInputChange } from '../../../hooks/common/use-on-input-change'
|
||||||
|
import { UsernameField } from '../../common/fields/username-field'
|
||||||
import { PasswordField } from './fields/password-field'
|
import { PasswordField } from './fields/password-field'
|
||||||
import { UsernameField } from './fields/username-field'
|
|
||||||
import { fetchAndSetUser } from './utils'
|
import { fetchAndSetUser } from './utils'
|
||||||
import type { FormEvent } from 'react'
|
import type { FormEvent } from 'react'
|
||||||
import React, { useCallback, useState } from 'react'
|
import React, { useCallback, useState } from 'react'
|
||||||
|
@ -49,7 +49,7 @@ export const ViaLdap: React.FC<ViaLdapProps> = ({ providerName, identifier }) =>
|
||||||
<Trans i18nKey='login.signInVia' values={{ service: providerName }} />
|
<Trans i18nKey='login.signInVia' values={{ service: providerName }} />
|
||||||
</Card.Title>
|
</Card.Title>
|
||||||
<Form onSubmit={onLoginSubmit}>
|
<Form onSubmit={onLoginSubmit}>
|
||||||
<UsernameField onChange={onUsernameChange} invalid={!!error} value={username} />
|
<UsernameField onChange={onUsernameChange} isValid={!!error} value={username} />
|
||||||
<PasswordField onChange={onPasswordChange} invalid={!!error} />
|
<PasswordField onChange={onPasswordChange} invalid={!!error} />
|
||||||
<Alert className='small' show={!!error} variant='danger'>
|
<Alert className='small' show={!!error} variant='danger'>
|
||||||
<Trans i18nKey={error} />
|
<Trans i18nKey={error} />
|
||||||
|
|
|
@ -7,10 +7,10 @@ import { doLocalLogin } from '../../../api/auth/local'
|
||||||
import { ErrorToI18nKeyMapper } from '../../../api/common/error-to-i18n-key-mapper'
|
import { ErrorToI18nKeyMapper } from '../../../api/common/error-to-i18n-key-mapper'
|
||||||
import { useLowercaseOnInputChange } from '../../../hooks/common/use-lowercase-on-input-change'
|
import { useLowercaseOnInputChange } from '../../../hooks/common/use-lowercase-on-input-change'
|
||||||
import { useOnInputChange } from '../../../hooks/common/use-on-input-change'
|
import { useOnInputChange } from '../../../hooks/common/use-on-input-change'
|
||||||
|
import { UsernameField } from '../../common/fields/username-field'
|
||||||
import { useFrontendConfig } from '../../common/frontend-config-context/use-frontend-config'
|
import { useFrontendConfig } from '../../common/frontend-config-context/use-frontend-config'
|
||||||
import { ShowIf } from '../../common/show-if/show-if'
|
import { ShowIf } from '../../common/show-if/show-if'
|
||||||
import { PasswordField } from './fields/password-field'
|
import { PasswordField } from './fields/password-field'
|
||||||
import { UsernameField } from './fields/username-field'
|
|
||||||
import { fetchAndSetUser } from './utils'
|
import { fetchAndSetUser } from './utils'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import type { FormEvent } from 'react'
|
import type { FormEvent } from 'react'
|
||||||
|
@ -55,7 +55,7 @@ export const ViaLocal: React.FC = () => {
|
||||||
<Trans i18nKey='login.signInVia' values={{ service: t('login.auth.username') }} />
|
<Trans i18nKey='login.signInVia' values={{ service: t('login.auth.username') }} />
|
||||||
</Card.Title>
|
</Card.Title>
|
||||||
<Form onSubmit={onLoginSubmit} className={'d-flex gap-3 flex-column'}>
|
<Form onSubmit={onLoginSubmit} className={'d-flex gap-3 flex-column'}>
|
||||||
<UsernameField onChange={onUsernameChange} invalid={!!error} value={username} />
|
<UsernameField onChange={onUsernameChange} isInvalid={!!error} value={username} />
|
||||||
<PasswordField onChange={onPasswordChange} invalid={!!error} />
|
<PasswordField onChange={onPasswordChange} invalid={!!error} />
|
||||||
<Alert className='small' show={!!error} variant='danger'>
|
<Alert className='small' show={!!error} variant='danger'>
|
||||||
<Trans i18nKey={error} />
|
<Trans i18nKey={error} />
|
||||||
|
|
|
@ -8,7 +8,7 @@ import type { ApiError } from '../api/common/api-error'
|
||||||
import { DisplayNameField } from '../components/common/fields/display-name-field'
|
import { DisplayNameField } from '../components/common/fields/display-name-field'
|
||||||
import { NewPasswordField } from '../components/common/fields/new-password-field'
|
import { NewPasswordField } from '../components/common/fields/new-password-field'
|
||||||
import { PasswordAgainField } from '../components/common/fields/password-again-field'
|
import { PasswordAgainField } from '../components/common/fields/password-again-field'
|
||||||
import { UsernameField } from '../components/common/fields/username-field'
|
import { UsernameLabelField } from '../components/common/fields/username-label-field'
|
||||||
import { useFrontendConfig } from '../components/common/frontend-config-context/use-frontend-config'
|
import { useFrontendConfig } from '../components/common/frontend-config-context/use-frontend-config'
|
||||||
import { Redirect } from '../components/common/redirect'
|
import { Redirect } from '../components/common/redirect'
|
||||||
import { LandingLayout } from '../components/landing-layout/landing-layout'
|
import { LandingLayout } from '../components/landing-layout/landing-layout'
|
||||||
|
@ -63,6 +63,8 @@ export const RegisterPage: NextPage = () => {
|
||||||
return error?.backendErrorName === 'PasswordTooWeakError'
|
return error?.backendErrorName === 'PasswordTooWeakError'
|
||||||
}, [error])
|
}, [error])
|
||||||
|
|
||||||
|
const isValidUsername = useMemo(() => Boolean(username.trim()), [username])
|
||||||
|
|
||||||
const onUsernameChange = useLowercaseOnInputChange(setUsername)
|
const onUsernameChange = useLowercaseOnInputChange(setUsername)
|
||||||
const onDisplayNameChange = useOnInputChange(setDisplayName)
|
const onDisplayNameChange = useOnInputChange(setDisplayName)
|
||||||
const onPasswordChange = useOnInputChange(setPassword)
|
const onPasswordChange = useOnInputChange(setPassword)
|
||||||
|
@ -87,7 +89,7 @@ export const RegisterPage: NextPage = () => {
|
||||||
<Card className='mb-4 text-start'>
|
<Card className='mb-4 text-start'>
|
||||||
<Card.Body>
|
<Card.Body>
|
||||||
<Form onSubmit={doRegisterSubmit} className={'d-flex flex-column gap-3'}>
|
<Form onSubmit={doRegisterSubmit} className={'d-flex flex-column gap-3'}>
|
||||||
<UsernameField onChange={onUsernameChange} value={username} />
|
<UsernameLabelField onChange={onUsernameChange} value={username} isValid={isValidUsername} />
|
||||||
<DisplayNameField onChange={onDisplayNameChange} value={displayName} />
|
<DisplayNameField onChange={onDisplayNameChange} value={displayName} />
|
||||||
<NewPasswordField onChange={onPasswordChange} value={password} hasError={isWeakPassword} />
|
<NewPasswordField onChange={onPasswordChange} value={password} hasError={isWeakPassword} />
|
||||||
<PasswordAgainField
|
<PasswordAgainField
|
||||||
|
|
Loading…
Reference in a new issue