Bring in the change password section

This also changes the layout slightly in the user settings, but nothing detrimental.
pull/21833/head
Travis Ralston 2019-01-22 13:09:40 -07:00
parent 677b3ca7b5
commit 19de6694ca
7 changed files with 94 additions and 36 deletions

View File

@ -88,4 +88,22 @@
.mx_GeneralSettingsTab_profileAvatarUpload {
display: none;
}
.mx_GeneralSettingsTab_changePassword {
display: block;
}
.mx_GeneralSettingsTab_changePassword .mx_Field {
display: block;
margin-right: 100px; // Align with the other fields on the page
}
.mx_GeneralSettingsTab_changePassword .mx_Field input {
display: block;
width: calc(100% - 20px); // subtract 10px padding on left and right
}
.mx_GeneralSettingsTab_changePassword .mx_Field:first-child {
margin-top: 0;
}

View File

@ -1268,9 +1268,7 @@ module.exports = React.createClass({
<ChangePassword
className="mx_UserSettings_accountTable"
rowClassName="mx_UserSettings_profileTableRow"
rowLabelClassName="mx_UserSettings_profileLabelCell"
rowInputClassName="mx_UserSettings_profileInputCell"
buttonClassName="mx_UserSettings_button mx_UserSettings_changePasswordButton"
buttonClassName="mx_UserSettings_button"
onError={this.onPasswordChangeError}
onFinished={this.onPasswordChanged} />
);

View File

@ -116,9 +116,8 @@ export default React.createClass({
<ChangePassword
className="mx_SetPasswordDialog_change_password"
rowClassName=""
rowLabelClassName=""
rowInputClassName=""
buttonClassName="mx_Dialog_primary mx_SetPasswordDialog_change_password_button"
buttonClassNames="mx_Dialog_primary mx_SetPasswordDialog_change_password_button"
buttonKind="primary"
confirm={false}
autoFocusNewPasswordInput={true}
shouldAskForEmail={true}

View File

@ -31,6 +31,11 @@ export default class Field extends React.PureComponent {
// To define options for a select, use <Field><option ... /></Field>
element: PropTypes.string,
// All other props pass through to the <input>.
};
get value() {
if (!this.refs.fieldInput) return null;
return this.refs.fieldInput.value;
}
render() {

View File

@ -15,6 +15,8 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import Field from "../elements/Field";
const React = require('react');
import PropTypes from 'prop-types';
const MatrixClientPeg = require("../../../MatrixClientPeg");
@ -35,9 +37,8 @@ module.exports = React.createClass({
onError: PropTypes.func,
onCheckPassword: PropTypes.func,
rowClassName: PropTypes.string,
rowLabelClassName: PropTypes.string,
rowInputClassName: PropTypes.string,
buttonClassName: PropTypes.string,
buttonKind: PropTypes.string,
confirm: PropTypes.bool,
// Whether to autoFocus the new password input
autoFocusNewPasswordInput: PropTypes.bool,
@ -203,21 +204,18 @@ module.exports = React.createClass({
},
render: function() {
// TODO: Live validation on `new pw == confirm pw`
const rowClassName = this.props.rowClassName;
const rowLabelClassName = this.props.rowLabelClassName;
const rowInputClassName = this.props.rowInputClassName;
const buttonClassName = this.props.buttonClassName;
let currentPassword = null;
if (!this.state.cachedPassword) {
currentPassword = <div className={rowClassName}>
<div className={rowLabelClassName}>
<label htmlFor="passwordold">{ _t('Current password') }</label>
currentPassword = (
<div className={rowClassName}>
<Field id="passwordold" type="password" ref="old_input" label={_t('Current password')} />
</div>
<div className={rowInputClassName}>
<input id="passwordold" type="password" ref="old_input" />
</div>
</div>;
);
}
switch (this.state.phase) {
@ -228,24 +226,13 @@ module.exports = React.createClass({
<form className={this.props.className} onSubmit={this.onClickChange}>
{ currentPassword }
<div className={rowClassName}>
<div className={rowLabelClassName}>
<label htmlFor="password1">{ passwordLabel }</label>
</div>
<div className={rowInputClassName}>
<input id="password1" type="password" ref="new_input" autoFocus={this.props.autoFocusNewPasswordInput} />
</div>
<Field id="password1" type="password" ref="new_input" label={passwordLabel}
autoFocus={this.props.autoFocusNewPasswordInput} />
</div>
<div className={rowClassName}>
<div className={rowLabelClassName}>
<label htmlFor="password2">{ _t('Confirm password') }</label>
</div>
<div className={rowInputClassName}>
<input id="password2" type="password" ref="confirm_input" />
</div>
<Field id="password2" type="password" ref="confirm_input" label={_t("Confirm password")} />
</div>
<AccessibleButton className={buttonClassName}
onClick={this.onClickChange}
element="button">
<AccessibleButton className={buttonClassName} kind={this.props.buttonKind} onClick={this.onClickChange}>
{ _t('Change Password') }
</AccessibleButton>
</form>

View File

@ -24,6 +24,8 @@ import GroupUserSettings from "../../groups/GroupUserSettings";
import PropTypes from "prop-types";
import {MatrixClient} from "matrix-js-sdk";
import { DragDropContext } from 'react-beautiful-dnd';
const sdk = require('../../../../index');
const Modal = require("../../../../Modal");
export default class GeneralSettingsTab extends React.Component {
static childContextTypes = {
@ -90,6 +92,13 @@ export default class GeneralSettingsTab extends React.Component {
this.setState(newState);
};
_changePassword = async (e) => {
e.stopPropagation();
e.preventDefault();
console.log(this.refs.currentPassword);
};
_onDisplayNameChanged = (e) => {
this.setState({
displayName: e.target.value,
@ -119,6 +128,34 @@ export default class GeneralSettingsTab extends React.Component {
reader.readAsDataURL(file);
};
_onPasswordChangeError = (err) => {
// TODO: Figure out a design that doesn't involve replacing the current dialog
let errMsg = err.error || "";
if (err.httpStatus === 403) {
errMsg = _t("Failed to change password. Is your password correct?");
} else if (err.httpStatus) {
errMsg += ` (HTTP status ${err.httpStatus})`;
}
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
console.error("Failed to change password: " + errMsg);
Modal.createTrackedDialog('Failed to change password', '', ErrorDialog, {
title: _t("Error"),
description: errMsg,
});
};
_onPasswordChanged = () => {
// TODO: Figure out a design that doesn't involve replacing the current dialog
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
Modal.createTrackedDialog('Password changed', '', ErrorDialog, {
title: _t("Success"),
description: _t(
"Your password was successfully changed. You will not receive " +
"push notifications on other devices until you log back in to them",
) + ".",
});
};
_renderProfileSection() {
// TODO: Why is rendering a box with an overlay so complicated? Can the DOM be reduced?
@ -181,10 +218,23 @@ export default class GeneralSettingsTab extends React.Component {
}
_renderAccountSection() {
const ChangePassword = sdk.getComponent("views.settings.ChangePassword");
const passwordChangeForm = (
<ChangePassword
className="mx_GeneralSettingsTab_changePassword"
rowClassName=""
buttonKind="primary"
onError={this._onPasswordChangeError}
onFinished={this._onPasswordChanged} />
);
return (
<div className="mx_SettingsTab_section">
<span className="mx_SettingsTab_subheading">{_t("Account")}</span>
<p>ACCOUNT SECTION</p>
<p className="mx_SettingsTab_subsectionText">
{_t("Set a new account password...")}
</p>
{passwordChangeForm}
</div>
);
}

View File

@ -402,6 +402,9 @@
"Off": "Off",
"On": "On",
"Noisy": "Noisy",
"Failed to change password. Is your password correct?": "Failed to change password. Is your password correct?",
"Success": "Success",
"Your password was successfully changed. You will not receive push notifications on other devices until you log back in to them": "Your password was successfully changed. You will not receive push notifications on other devices until you log back in to them",
"Profile picture": "Profile picture",
"Upload profile picture": "Upload profile picture",
"Display Name": "Display Name",
@ -409,6 +412,7 @@
"Profile": "Profile",
"Flair": "Flair",
"Account": "Account",
"Set a new account password...": "Set a new account password...",
"Language and region": "Language and region",
"Theme": "Theme",
"Account management": "Account management",
@ -1000,7 +1004,6 @@
"You have successfully set a password and an email address!": "You have successfully set a password and an email address!",
"You can now return to your account after signing out, and sign in on other devices.": "You can now return to your account after signing out, and sign in on other devices.",
"Remember, you can always set an email address in user settings if you change your mind.": "Remember, you can always set an email address in user settings if you change your mind.",
"Failed to change password. Is your password correct?": "Failed to change password. Is your password correct?",
"(HTTP status %(httpStatus)s)": "(HTTP status %(httpStatus)s)",
"Please set a password!": "Please set a password!",
"This will allow you to return to your account after signing out, and sign in on other devices.": "This will allow you to return to your account after signing out, and sign in on other devices.",
@ -1248,8 +1251,6 @@
"Status.im theme": "Status.im theme",
"Can't load user settings": "Can't load user settings",
"Server may be unavailable or overloaded": "Server may be unavailable or overloaded",
"Success": "Success",
"Your password was successfully changed. You will not receive push notifications on other devices until you log back in to them": "Your password was successfully changed. You will not receive push notifications on other devices until you log back in to them",
"Remove Contact Information?": "Remove Contact Information?",
"Remove %(threePid)s?": "Remove %(threePid)s?",
"Unable to remove contact information": "Unable to remove contact information",