Merge branch 'showable-password' into 'develop'

Create ShowablePassword component

See merge request soapbox-pub/soapbox-fe!916
strip-front-mentions
Alex Gleason 2021-12-15 15:07:33 +00:00
commit 7f3d7fbc29
10 zmienionych plików z 210 dodań i 37 usunięć

Wyświetl plik

@ -0,0 +1,64 @@
import React from 'react';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { defineMessages, injectIntl } from 'react-intl';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import IconButton from 'soapbox/components/icon_button';
import { FormPropTypes, InputContainer, LabelInputContainer } from 'soapbox/features/forms';
const messages = defineMessages({
showPassword: { id: 'forms.show_password', defaultMessage: 'Show password' },
hidePassword: { id: 'forms.hide_password', defaultMessage: 'Hide password' },
});
export default @injectIntl
class ShowablePassword extends ImmutablePureComponent {
static propTypes = {
intl: PropTypes.object.isRequired,
label: FormPropTypes.label,
className: PropTypes.string,
hint: PropTypes.node,
error: PropTypes.bool,
}
state = {
revealed: false,
}
toggleReveal = () => {
if (this.props.onToggleVisibility) {
this.props.onToggleVisibility();
} else {
this.setState({ revealed: !this.state.revealed });
}
}
render() {
const { intl, hint, error, label, className, ...props } = this.props;
const { revealed } = this.state;
const revealButton = (
<IconButton
src={revealed ? require('@tabler/icons/icons/eye.svg') : require('@tabler/icons/icons/eye-off.svg')}
onClick={this.toggleReveal}
title={intl.formatMessage(revealed ? messages.hidePassword : messages.showPassword)}
/>
);
return (
<InputContainer {...this.props} extraClass={classNames('showable-password', className)}>
{label ? (
<LabelInputContainer label={label}>
<input {...props} type={revealed ? 'text' : 'password'} />
{revealButton}
</LabelInputContainer>
) : (<>
<input {...props} type={revealed ? 'text' : 'password'} />
{revealButton}
</>)}
</InputContainer>
);
}
}

Wyświetl plik

@ -25,19 +25,48 @@ exports[`<LoginForm /> renders for Mastodon 1`] = `
/>
</div>
<div
className="input password user_password"
className="input required showable-password password user_password"
>
<input
aria-label="Password"
autoCapitalize="off"
autoComplete="off"
autoCorrect="off"
className="password"
name="password"
placeholder="Password"
required={true}
type="password"
/>
<button
aria-label="Show password"
className="icon-button"
disabled={false}
onClick={[Function]}
onKeyDown={[Function]}
onKeyPress={[Function]}
onKeyUp={[Function]}
onMouseDown={[Function]}
onMouseEnter={[Function]}
onMouseLeave={[Function]}
tabIndex="0"
title="Show password"
>
<div
style={Object {}}
>
<div
className="svg-icon"
>
<svg
id={
Object {
"process": [Function],
}
}
/>
</div>
</div>
</button>
</div>
<p
className="hint subtle-hint"
@ -89,19 +118,48 @@ exports[`<LoginForm /> renders for Pleroma 1`] = `
/>
</div>
<div
className="input password user_password"
className="input required showable-password password user_password"
>
<input
aria-label="Password"
autoCapitalize="off"
autoComplete="off"
autoCorrect="off"
className="password"
name="password"
placeholder="Password"
required={true}
type="password"
/>
<button
aria-label="Show password"
className="icon-button"
disabled={false}
onClick={[Function]}
onKeyDown={[Function]}
onKeyPress={[Function]}
onKeyUp={[Function]}
onMouseDown={[Function]}
onMouseEnter={[Function]}
onMouseLeave={[Function]}
tabIndex="0"
title="Show password"
>
<div
style={Object {}}
>
<div
className="svg-icon"
>
<svg
id={
Object {
"process": [Function],
}
}
/>
</div>
</div>
</button>
</div>
<p
className="hint subtle-hint"

Wyświetl plik

@ -28,19 +28,48 @@ exports[`<LoginPage /> renders correctly on load 1`] = `
/>
</div>
<div
className="input password user_password"
className="input required showable-password password user_password"
>
<input
aria-label="Password"
autoCapitalize="off"
autoComplete="off"
autoCorrect="off"
className="password"
name="password"
placeholder="Password"
required={true}
type="password"
/>
<button
aria-label="Show password"
className="icon-button"
disabled={false}
onClick={[Function]}
onKeyDown={[Function]}
onKeyPress={[Function]}
onKeyUp={[Function]}
onMouseDown={[Function]}
onMouseEnter={[Function]}
onMouseLeave={[Function]}
tabIndex="0"
title="Show password"
>
<div
style={Object {}}
>
<div
className="svg-icon"
>
<svg
id={
Object {
"process": [Function],
}
}
/>
</div>
</div>
</button>
</div>
<p
className="hint subtle-hint"

Wyświetl plik

@ -5,6 +5,7 @@ import { Link } from 'react-router-dom';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { getFeatures } from 'soapbox/utils/features';
import { getBaseURL } from 'soapbox/utils/state';
import ShowablePassword from 'soapbox/components/showable_password';
const messages = defineMessages({
username: { id: 'login.fields.username_placeholder', defaultMessage: 'Username' },
@ -45,19 +46,20 @@ class LoginForm extends ImmutablePureComponent {
required
/>
</div>
<div className='input password user_password'>
<ShowablePassword
aria-label={intl.formatMessage(messages.password)}
className='password user_password'
placeholder={intl.formatMessage(messages.password)}
name='password'
autoComplete='off'
autoCorrect='off'
autoCapitalize='off'
required
/>
{/* <div className='input password user_password'>
<input
aria-label={intl.formatMessage(messages.password)}
className='password'
placeholder={intl.formatMessage(messages.password)}
type='password'
name='password'
autoComplete='off'
autoCorrect='off'
autoCapitalize='off'
required
/>
</div>
</div> */}
<p className='hint subtle-hint'>
{hasResetPasswordAPI ? (
<Link to='/auth/reset_password'>

Wyświetl plik

@ -5,6 +5,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
import { connect } from 'react-redux';
import { injectIntl, FormattedMessage, defineMessages } from 'react-intl';
import { Link } from 'react-router-dom';
import ShowablePassword from 'soapbox/components/showable_password';
import {
SimpleForm,
SimpleInput,
@ -231,10 +232,9 @@ class RegistrationForm extends ImmutablePureComponent {
<FormattedMessage id='registration.password_mismatch' defaultMessage="Passwords don't match." />
</div>
)}
<SimpleInput
<ShowablePassword
placeholder={intl.formatMessage(messages.password)}
name='password'
type='password'
autoComplete='off'
autoCorrect='off'
autoCapitalize='off'
@ -243,10 +243,9 @@ class RegistrationForm extends ImmutablePureComponent {
error={passwordMismatch === true}
required
/>
<SimpleInput
<ShowablePassword
placeholder={intl.formatMessage(messages.confirm)}
name='password_confirmation'
type='password'
autoComplete='off'
autoCorrect='off'
autoCapitalize='off'

Wyświetl plik

@ -6,9 +6,9 @@ import PropTypes from 'prop-types';
import ImmutablePropTypes from 'react-immutable-proptypes';
import Column from '../ui/components/column';
import Button from 'soapbox/components/button';
import ShowablePassword from 'soapbox/components/showable_password';
import {
SimpleForm,
SimpleInput,
FieldsGroup,
TextInput,
} from 'soapbox/features/forms';
@ -141,8 +141,7 @@ class ChangeEmailForm extends ImmutablePureComponent {
onChange={this.handleInputChange}
value={this.state.email}
/>
<SimpleInput
type='password'
<ShowablePassword
label={intl.formatMessage(messages.passwordFieldLabel)}
name='password'
onChange={this.handleInputChange}
@ -208,22 +207,19 @@ class ChangePasswordForm extends ImmutablePureComponent {
<h2>{intl.formatMessage(messages.passwordHeader)}</h2>
<fieldset disabled={this.state.isLoading}>
<FieldsGroup>
<SimpleInput
type='password'
<ShowablePassword
label={intl.formatMessage(messages.oldPasswordFieldLabel)}
name='oldPassword'
onChange={this.handleInputChange}
value={this.state.oldPassword}
/>
<SimpleInput
type='password'
<ShowablePassword
label={intl.formatMessage(messages.newPasswordFieldLabel)}
name='newPassword'
onChange={this.handleInputChange}
value={this.state.newPassword}
/>
<SimpleInput
type='password'
<ShowablePassword
label={intl.formatMessage(messages.confirmationFieldLabel)}
name='confirmation'
onChange={this.handleInputChange}
@ -392,8 +388,7 @@ class DeactivateAccount extends ImmutablePureComponent {
</p>
<fieldset disabled={this.state.isLoading}>
<FieldsGroup>
<SimpleInput
type='password'
<ShowablePassword
label={intl.formatMessage(messages.passwordFieldLabel)}
name='password'
onChange={this.handleInputChange}

Wyświetl plik

@ -11,9 +11,9 @@ import LoadingIndicator from 'soapbox/components/loading_indicator';
import Button from 'soapbox/components/button';
import { changeSetting, getSettings } from 'soapbox/actions/settings';
import snackbar from 'soapbox/actions/snackbar';
import ShowablePassword from 'soapbox/components/showable_password';
import {
SimpleForm,
SimpleInput,
FieldsGroup,
TextInput,
} from 'soapbox/features/forms';
@ -144,8 +144,7 @@ class DisableOtpForm extends ImmutablePureComponent {
</h1>
<div><FormattedMessage id='mfa.otp_enabled_description' defaultMessage='You have enabled two-factor authentication via OTP.' /></div>
<div><FormattedMessage id='mfa.mfa_disable_enter_password' defaultMessage='Enter your current password to disable two-factor auth:' /></div>
<SimpleInput
type='password'
<ShowablePassword
name='password'
onChange={this.handleInputChange}
/>
@ -313,8 +312,7 @@ class OtpConfirmForm extends ImmutablePureComponent {
/>
<div><FormattedMessage id='mfa.mfa_setup_enter_password' defaultMessage='Enter your current password to confirm your identity:' /></div>
<SimpleInput
type='password'
<ShowablePassword
name='password'
onChange={this.handleInputChange}
/>

Wyświetl plik

@ -424,6 +424,8 @@
"follow_request.authorize": "Autoryzuj",
"follow_request.reject": "Odrzuć",
"forms.copy": "Kopiuj",
"forms.hide_password": "Ukryj hasło",
"forms.show_password": "Pokaż hasło",
"getting_started.open_source_notice": "{code_name} jest oprogramowaniem o otwartym źródle. Możesz pomóc w rozwoju lub zgłaszać błędy na GitLabie tutaj: {code_link} (v{code_version}).",
"group.detail.archived_group": "Zarchiwizowana grupa",
"group.members.empty": "Ta grupa nie ma żadnych członków.",

Wyświetl plik

@ -97,6 +97,7 @@ $fluid-breakpoint: $maximum-width + 20px;
}
.input {
flex: 1;
margin-bottom: 0;
margin-right: 10px;

Wyświetl plik

@ -608,6 +608,31 @@ code {
margin-bottom: 14px;
font-weight: bold;
}
.showable-password {
position: relative;
input {
padding-right: 36px;
}
.icon-button {
position: absolute;
top: 0;
right: 0;
height: 41px;
width: 36px;
padding: 0;
margin: 0;
background: transparent;
color: var(--primary-text-color);
.svg-icon {
height: 20px;
width: 20px;
}
}
}
}
.block-icon {