Bring in the change password section
This also changes the layout slightly in the user settings, but nothing detrimental.pull/21833/head
parent
677b3ca7b5
commit
19de6694ca
|
@ -88,4 +88,22 @@
|
||||||
|
|
||||||
.mx_GeneralSettingsTab_profileAvatarUpload {
|
.mx_GeneralSettingsTab_profileAvatarUpload {
|
||||||
display: none;
|
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;
|
||||||
}
|
}
|
|
@ -1268,9 +1268,7 @@ module.exports = React.createClass({
|
||||||
<ChangePassword
|
<ChangePassword
|
||||||
className="mx_UserSettings_accountTable"
|
className="mx_UserSettings_accountTable"
|
||||||
rowClassName="mx_UserSettings_profileTableRow"
|
rowClassName="mx_UserSettings_profileTableRow"
|
||||||
rowLabelClassName="mx_UserSettings_profileLabelCell"
|
buttonClassName="mx_UserSettings_button"
|
||||||
rowInputClassName="mx_UserSettings_profileInputCell"
|
|
||||||
buttonClassName="mx_UserSettings_button mx_UserSettings_changePasswordButton"
|
|
||||||
onError={this.onPasswordChangeError}
|
onError={this.onPasswordChangeError}
|
||||||
onFinished={this.onPasswordChanged} />
|
onFinished={this.onPasswordChanged} />
|
||||||
);
|
);
|
||||||
|
|
|
@ -116,9 +116,8 @@ export default React.createClass({
|
||||||
<ChangePassword
|
<ChangePassword
|
||||||
className="mx_SetPasswordDialog_change_password"
|
className="mx_SetPasswordDialog_change_password"
|
||||||
rowClassName=""
|
rowClassName=""
|
||||||
rowLabelClassName=""
|
buttonClassNames="mx_Dialog_primary mx_SetPasswordDialog_change_password_button"
|
||||||
rowInputClassName=""
|
buttonKind="primary"
|
||||||
buttonClassName="mx_Dialog_primary mx_SetPasswordDialog_change_password_button"
|
|
||||||
confirm={false}
|
confirm={false}
|
||||||
autoFocusNewPasswordInput={true}
|
autoFocusNewPasswordInput={true}
|
||||||
shouldAskForEmail={true}
|
shouldAskForEmail={true}
|
||||||
|
|
|
@ -31,6 +31,11 @@ export default class Field extends React.PureComponent {
|
||||||
// To define options for a select, use <Field><option ... /></Field>
|
// To define options for a select, use <Field><option ... /></Field>
|
||||||
element: PropTypes.string,
|
element: PropTypes.string,
|
||||||
// All other props pass through to the <input>.
|
// All other props pass through to the <input>.
|
||||||
|
};
|
||||||
|
|
||||||
|
get value() {
|
||||||
|
if (!this.refs.fieldInput) return null;
|
||||||
|
return this.refs.fieldInput.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
|
|
@ -15,6 +15,8 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import Field from "../elements/Field";
|
||||||
|
|
||||||
const React = require('react');
|
const React = require('react');
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
const MatrixClientPeg = require("../../../MatrixClientPeg");
|
const MatrixClientPeg = require("../../../MatrixClientPeg");
|
||||||
|
@ -35,9 +37,8 @@ module.exports = React.createClass({
|
||||||
onError: PropTypes.func,
|
onError: PropTypes.func,
|
||||||
onCheckPassword: PropTypes.func,
|
onCheckPassword: PropTypes.func,
|
||||||
rowClassName: PropTypes.string,
|
rowClassName: PropTypes.string,
|
||||||
rowLabelClassName: PropTypes.string,
|
|
||||||
rowInputClassName: PropTypes.string,
|
|
||||||
buttonClassName: PropTypes.string,
|
buttonClassName: PropTypes.string,
|
||||||
|
buttonKind: PropTypes.string,
|
||||||
confirm: PropTypes.bool,
|
confirm: PropTypes.bool,
|
||||||
// Whether to autoFocus the new password input
|
// Whether to autoFocus the new password input
|
||||||
autoFocusNewPasswordInput: PropTypes.bool,
|
autoFocusNewPasswordInput: PropTypes.bool,
|
||||||
|
@ -203,21 +204,18 @@ module.exports = React.createClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
render: function() {
|
render: function() {
|
||||||
|
// TODO: Live validation on `new pw == confirm pw`
|
||||||
|
|
||||||
const rowClassName = this.props.rowClassName;
|
const rowClassName = this.props.rowClassName;
|
||||||
const rowLabelClassName = this.props.rowLabelClassName;
|
|
||||||
const rowInputClassName = this.props.rowInputClassName;
|
|
||||||
const buttonClassName = this.props.buttonClassName;
|
const buttonClassName = this.props.buttonClassName;
|
||||||
|
|
||||||
let currentPassword = null;
|
let currentPassword = null;
|
||||||
if (!this.state.cachedPassword) {
|
if (!this.state.cachedPassword) {
|
||||||
currentPassword = <div className={rowClassName}>
|
currentPassword = (
|
||||||
<div className={rowLabelClassName}>
|
<div className={rowClassName}>
|
||||||
<label htmlFor="passwordold">{ _t('Current password') }</label>
|
<Field id="passwordold" type="password" ref="old_input" label={_t('Current password')} />
|
||||||
</div>
|
</div>
|
||||||
<div className={rowInputClassName}>
|
);
|
||||||
<input id="passwordold" type="password" ref="old_input" />
|
|
||||||
</div>
|
|
||||||
</div>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (this.state.phase) {
|
switch (this.state.phase) {
|
||||||
|
@ -228,24 +226,13 @@ module.exports = React.createClass({
|
||||||
<form className={this.props.className} onSubmit={this.onClickChange}>
|
<form className={this.props.className} onSubmit={this.onClickChange}>
|
||||||
{ currentPassword }
|
{ currentPassword }
|
||||||
<div className={rowClassName}>
|
<div className={rowClassName}>
|
||||||
<div className={rowLabelClassName}>
|
<Field id="password1" type="password" ref="new_input" label={passwordLabel}
|
||||||
<label htmlFor="password1">{ passwordLabel }</label>
|
autoFocus={this.props.autoFocusNewPasswordInput} />
|
||||||
</div>
|
|
||||||
<div className={rowInputClassName}>
|
|
||||||
<input id="password1" type="password" ref="new_input" autoFocus={this.props.autoFocusNewPasswordInput} />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div className={rowClassName}>
|
<div className={rowClassName}>
|
||||||
<div className={rowLabelClassName}>
|
<Field id="password2" type="password" ref="confirm_input" label={_t("Confirm password")} />
|
||||||
<label htmlFor="password2">{ _t('Confirm password') }</label>
|
|
||||||
</div>
|
|
||||||
<div className={rowInputClassName}>
|
|
||||||
<input id="password2" type="password" ref="confirm_input" />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<AccessibleButton className={buttonClassName}
|
<AccessibleButton className={buttonClassName} kind={this.props.buttonKind} onClick={this.onClickChange}>
|
||||||
onClick={this.onClickChange}
|
|
||||||
element="button">
|
|
||||||
{ _t('Change Password') }
|
{ _t('Change Password') }
|
||||||
</AccessibleButton>
|
</AccessibleButton>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -24,6 +24,8 @@ import GroupUserSettings from "../../groups/GroupUserSettings";
|
||||||
import PropTypes from "prop-types";
|
import PropTypes from "prop-types";
|
||||||
import {MatrixClient} from "matrix-js-sdk";
|
import {MatrixClient} from "matrix-js-sdk";
|
||||||
import { DragDropContext } from 'react-beautiful-dnd';
|
import { DragDropContext } from 'react-beautiful-dnd';
|
||||||
|
const sdk = require('../../../../index');
|
||||||
|
const Modal = require("../../../../Modal");
|
||||||
|
|
||||||
export default class GeneralSettingsTab extends React.Component {
|
export default class GeneralSettingsTab extends React.Component {
|
||||||
static childContextTypes = {
|
static childContextTypes = {
|
||||||
|
@ -90,6 +92,13 @@ export default class GeneralSettingsTab extends React.Component {
|
||||||
this.setState(newState);
|
this.setState(newState);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
_changePassword = async (e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
console.log(this.refs.currentPassword);
|
||||||
|
};
|
||||||
|
|
||||||
_onDisplayNameChanged = (e) => {
|
_onDisplayNameChanged = (e) => {
|
||||||
this.setState({
|
this.setState({
|
||||||
displayName: e.target.value,
|
displayName: e.target.value,
|
||||||
|
@ -119,6 +128,34 @@ export default class GeneralSettingsTab extends React.Component {
|
||||||
reader.readAsDataURL(file);
|
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() {
|
_renderProfileSection() {
|
||||||
// TODO: Why is rendering a box with an overlay so complicated? Can the DOM be reduced?
|
// 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() {
|
_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 (
|
return (
|
||||||
<div className="mx_SettingsTab_section">
|
<div className="mx_SettingsTab_section">
|
||||||
<span className="mx_SettingsTab_subheading">{_t("Account")}</span>
|
<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>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -402,6 +402,9 @@
|
||||||
"Off": "Off",
|
"Off": "Off",
|
||||||
"On": "On",
|
"On": "On",
|
||||||
"Noisy": "Noisy",
|
"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",
|
"Profile picture": "Profile picture",
|
||||||
"Upload profile picture": "Upload profile picture",
|
"Upload profile picture": "Upload profile picture",
|
||||||
"Display Name": "Display Name",
|
"Display Name": "Display Name",
|
||||||
|
@ -409,6 +412,7 @@
|
||||||
"Profile": "Profile",
|
"Profile": "Profile",
|
||||||
"Flair": "Flair",
|
"Flair": "Flair",
|
||||||
"Account": "Account",
|
"Account": "Account",
|
||||||
|
"Set a new account password...": "Set a new account password...",
|
||||||
"Language and region": "Language and region",
|
"Language and region": "Language and region",
|
||||||
"Theme": "Theme",
|
"Theme": "Theme",
|
||||||
"Account management": "Account management",
|
"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 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.",
|
"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.",
|
"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)",
|
"(HTTP status %(httpStatus)s)": "(HTTP status %(httpStatus)s)",
|
||||||
"Please set a password!": "Please set a password!",
|
"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.",
|
"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",
|
"Status.im theme": "Status.im theme",
|
||||||
"Can't load user settings": "Can't load user settings",
|
"Can't load user settings": "Can't load user settings",
|
||||||
"Server may be unavailable or overloaded": "Server may be unavailable or overloaded",
|
"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 Contact Information?": "Remove Contact Information?",
|
||||||
"Remove %(threePid)s?": "Remove %(threePid)s?",
|
"Remove %(threePid)s?": "Remove %(threePid)s?",
|
||||||
"Unable to remove contact information": "Unable to remove contact information",
|
"Unable to remove contact information": "Unable to remove contact information",
|
||||||
|
|
Loading…
Reference in New Issue