Commit 1bebb395 authored by Nicolas Frandeboeuf's avatar Nicolas Frandeboeuf
Browse files

Allow to show/hide password in password inputs (fix #578)

parent 1a5d845a
Pipeline #15564 passed with stage
in 2 minutes and 20 seconds
......@@ -2,6 +2,8 @@ import React from 'react';
import { translate as $t } from '../../../helpers';
import PasswordInput from '../../ui/password-input';
class CustomBankField extends React.Component {
constructor(props) {
......@@ -12,17 +14,30 @@ class CustomBankField extends React.Component {
getValue() {
let node = this.fieldInput;
let value;
switch (this.props.params.type) {
case 'password':
value = node.getValue();
break;
case 'number':
value = parseInt(node.value, 10);
break;
default:
value = node.value;
}
return {
name: this.props.params.name,
value: (this.props.params.type === 'number') ?
parseInt(node.value, 10) :
node.value
value
};
}
render() {
let customFieldFormInput, customFieldOptions, defaultValue;
let fieldInputCb = input => {
let refFieldInput = input => {
this.fieldInput = input;
};
......@@ -38,10 +53,9 @@ class CustomBankField extends React.Component {
defaultValue = this.props.params.currentValue || this.props.params.default;
customFieldFormInput = (
<select
name={ this.props.params.name }
className="form-control"
id={ this.props.params.name }
ref={ fieldInputCb }
ref={ refFieldInput }
defaultValue={ defaultValue }>
{ customFieldOptions }
</select>
......@@ -50,14 +64,12 @@ class CustomBankField extends React.Component {
case 'text':
case 'number':
case 'password':
customFieldFormInput = (
<input
name={ this.props.params.name }
type={ this.props.params.type }
className="form-control"
id={ this.props.params.name }
ref={ fieldInputCb }
ref={ refFieldInput }
placeholder={ this.props.params.placeholderKey ?
$t(this.props.params.placeholderKey) :
'' }
......@@ -66,6 +78,18 @@ class CustomBankField extends React.Component {
);
break;
case 'password':
customFieldFormInput = (
<PasswordInput
id={ this.props.params.name }
ref={ refFieldInput }
placeholder={ this.props.params.placeholderKey ?
$t(this.props.params.placeholderKey) :
'' }
/>
);
break;
default:
alert($t('client.settings.unknown_field_type'));
}
......
......@@ -4,6 +4,7 @@ import { translate as $t } from '../../../helpers';
import CustomBankField from './custom-bank-field';
import Modal from '../../ui/modal';
import PasswordInput from '../../ui/password-input';
class EditAccessModal extends React.Component {
......@@ -26,8 +27,8 @@ class EditAccessModal extends React.Component {
event.preventDefault();
let newLogin = this.loginInput.value.trim();
let newPassword = this.passwordInput.value.trim();
if (!newPassword || !newPassword.length) {
let newPassword = this.passwordInput.getValue();
if (!newPassword.length) {
alert($t('client.editaccessmodal.not_empty'));
return;
}
......@@ -42,7 +43,7 @@ class EditAccessModal extends React.Component {
}
this.props.onSave(newLogin, newPassword, customFields);
this.passwordInput.value = '';
this.passwordInput.clear();
$(`#${this.props.modalId}`).modal('hide');
}
......@@ -98,9 +99,7 @@ class EditAccessModal extends React.Component {
<label htmlFor="password">
{ $t('client.settings.password') }
</label>
<input
type="password"
className="form-control"
<PasswordInput
id="password"
ref={ passwordInputCb }
/>
......
......@@ -4,6 +4,8 @@ import { connect } from 'react-redux';
import { get, actions } from '../../../store';
import { assert, translate as $t } from '../../../helpers';
import PasswordInput from '../../ui/password-input';
import CustomBankField from './custom-bank-field';
class NewBankForm extends React.Component {
......@@ -60,7 +62,7 @@ class NewBankForm extends React.Component {
let uuid = this.bankSelector.value;
let login = this.loginInput.value.trim();
let password = this.passwordInput.value.trim();
let password = this.passwordInput.getValue();
let selectedBank = this.selectedBank();
......@@ -186,11 +188,9 @@ class NewBankForm extends React.Component {
<label htmlFor="password">
{ $t('client.settings.password') }
</label>
<input
type="password"
className="form-control"
id="password"
<PasswordInput
ref={ passwordInputCb }
id="password"
/>
</div>
</div>
......
......@@ -5,6 +5,7 @@ import { actions, get } from '../../../store';
import { translate as $t } from '../../../helpers';
import BoolSetting from '../../ui/bool-setting';
import PasswordInput from '../../ui/password-input';
class EmailConfig extends React.Component {
......@@ -41,7 +42,7 @@ class EmailConfig extends React.Component {
secure: this.secure,
auth: {
user: this.user.value && this.user.value.trim(),
pass: this.password.value && this.password.value.trim()
pass: this.password.getValue()
},
tls: {
rejectUnauthorized: this.rejectUnauthorized
......@@ -126,6 +127,7 @@ class EmailConfig extends React.Component {
<div className="col-xs-8">
<input
id="email_host"
className="form-control"
type="text"
ref={ refHost }
defaultValue={ this.props.config.host }
......@@ -142,6 +144,7 @@ class EmailConfig extends React.Component {
<div className="col-xs-8">
<input
id="email_port"
className="form-control"
type="text"
ref={ refPort }
defaultValue={ this.props.config.port }
......@@ -158,6 +161,7 @@ class EmailConfig extends React.Component {
<div className="col-xs-8">
<input
id="email_user"
className="form-control"
type="text"
ref={ refUser }
defaultValue={ this.props.config.user || '' }
......@@ -172,9 +176,8 @@ class EmailConfig extends React.Component {
{ $t('client.settings.emails.password') }
</label>
<div className="col-xs-8">
<input
<PasswordInput
id="email_password"
type="password"
ref={ refPassword }
/>
</div>
......@@ -189,6 +192,7 @@ class EmailConfig extends React.Component {
<div className="col-xs-8">
<input
id="email_send_from"
className="form-control"
type="text"
ref={ refFromEmail }
defaultValue={ this.props.config.fromEmail }
......@@ -205,6 +209,7 @@ class EmailConfig extends React.Component {
<div className="col-xs-8">
<input
id="email_send_to"
className="form-control"
type="text"
ref={ refToEmail }
defaultValue={ this.props.config.toEmail }
......
import React from 'react';
import { translate as $t } from '../../helpers';
class PasswordInput extends React.Component {
constructor(props) {
super(props);
this.state = {
showPassword: false
};
this.input = null;
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState({
showPassword: !this.state.showPassword
});
}
getValue() {
return (this.input.value || '').trim();
}
focus() {
this.input.focus();
}
clear() {
this.input.value = '';
}
render() {
let refInput = node => {
this.input = node;
};
let iconClass;
let type;
let title;
if (this.state.showPassword) {
iconClass = 'eye-slash';
type = 'text';
title = $t('client.general.hide_password');
} else {
iconClass = 'eye';
type = 'password';
title = $t('client.general.show_password');
}
return (
<div className="input-group">
<input
type={ type }
className="form-control"
id={ this.props.id }
ref={ refInput }
placeholder={ this.props.placeholder }
autoComplete="new-password"
/>
<span
className={ `clickable input-group-addon fa fa-${iconClass}` }
onClick={ this.handleClick }
title={ title }
/>
</div>
);
}
}
PasswordInput.propTypes = {
// The id attribute used to match labels.
id: React.PropTypes.string.isRequired,
// The input's placeholder.
placeholder: React.PropTypes.string
};
export default PasswordInput;
......@@ -803,6 +803,10 @@ table.budget td:last-child {
}
/* Settings section */
.emails .form-group > div {
max-width: 300px;
}
.emails .condition {
padding-right: 10px;
}
......
......@@ -701,7 +701,7 @@
"customFields": [
{
"labelKey": "client.settings.secret",
"type": "text",
"type": "password",
"name": "secret",
"placeholderKey": "client.settings.secret_placeholder"
}
......@@ -752,7 +752,7 @@
"customFields": [
{
"labelKey": "client.settings.secret",
"type": "text",
"type": "password",
"name": "secret",
"placeholderKey": "client.settings.secret_placeholder"
}
......
......@@ -82,7 +82,9 @@ module.exports = {
save: 'save',
default_parameters: 'Default parameters',
select_all: 'Select all',
unselect_all: 'Unselect all'
unselect_all: 'Unselect all',
show_password: 'Show the password',
hide_password: 'Hide the password'
},
menu: {
......
......@@ -82,7 +82,9 @@ module.exports = {
save: 'sauver',
default_parameters: 'Paramètres par défaut',
select_all: 'Sélectionner tout',
unselect_all: 'Déselectionner tout'
unselect_all: 'Déselectionner tout',
show_password: 'Afficher le mot de passe',
hide_password: 'Cacher le mot de passe'
},
menu: {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment