Merge pull request #33 from matrix-org/matthew/settings
WIP experiment of turning UserSettings controller into UserSettingsStore
This commit is contained in:
commit
b941904078
8 changed files with 388 additions and 150 deletions
67
src/UserSettingsStore.js
Normal file
67
src/UserSettingsStore.js
Normal file
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
Copyright 2015 OpenMarket Ltd
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var MatrixClientPeg = require("./MatrixClientPeg");
|
||||
var Notifier = require("./Notifier");
|
||||
|
||||
/*
|
||||
* TODO: Make things use this. This is all WIP - see UserSettings.js for usage.
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
|
||||
loadProfileInfo: function() {
|
||||
var cli = MatrixClientPeg.get();
|
||||
return cli.getProfileInfo(cli.credentials.userId);
|
||||
},
|
||||
|
||||
saveDisplayName: function(newDisplayname) {
|
||||
return MatrixClientPeg.get().setDisplayName(newDisplayname);
|
||||
},
|
||||
|
||||
loadThreePids: function() {
|
||||
return MatrixClientPeg.get().getThreePids();
|
||||
},
|
||||
|
||||
saveThreePids: function(threePids) {
|
||||
// TODO
|
||||
},
|
||||
|
||||
getEnableNotifications: function() {
|
||||
return Notifier.isEnabled();
|
||||
},
|
||||
|
||||
setEnableNotifications: function(enable) {
|
||||
if (!Notifier.supportsDesktopNotifications()) {
|
||||
return;
|
||||
}
|
||||
Notifier.setEnabled(enable);
|
||||
},
|
||||
|
||||
changePassword: function(old_password, new_password) {
|
||||
var cli = MatrixClientPeg.get();
|
||||
|
||||
var authDict = {
|
||||
type: 'm.login.password',
|
||||
user: cli.credentials.userId,
|
||||
password: old_password
|
||||
};
|
||||
|
||||
return cli.setPassword(authDict, new_password);
|
||||
},
|
||||
};
|
|
@ -628,6 +628,22 @@ module.exports = React.createClass({
|
|||
this.showScreen("settings");
|
||||
},
|
||||
|
||||
onUserSettingsClose: function() {
|
||||
// XXX: use browser history instead to find the previous room?
|
||||
if (this.state.currentRoom) {
|
||||
dis.dispatch({
|
||||
action: 'view_room',
|
||||
room_id: this.state.currentRoom,
|
||||
});
|
||||
}
|
||||
else {
|
||||
dis.dispatch({
|
||||
action: 'view_indexed_room',
|
||||
roomIndex: 0,
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var LeftPanel = sdk.getComponent('structures.LeftPanel');
|
||||
var RoomView = sdk.getComponent('structures.RoomView');
|
||||
|
@ -660,7 +676,7 @@ module.exports = React.createClass({
|
|||
right_panel = <RightPanel roomId={this.state.currentRoom} collapsed={this.state.collapse_rhs} />
|
||||
break;
|
||||
case this.PageTypes.UserSettings:
|
||||
page_element = <UserSettings />
|
||||
page_element = <UserSettings onClose={this.onUserSettingsClose} />
|
||||
right_panel = <RightPanel collapsed={this.state.collapse_rhs}/>
|
||||
break;
|
||||
case this.PageTypes.CreateRoom:
|
||||
|
|
|
@ -17,14 +17,22 @@ var React = require('react');
|
|||
var sdk = require('../../index');
|
||||
var MatrixClientPeg = require("../../MatrixClientPeg");
|
||||
var Modal = require('../../Modal');
|
||||
var dis = require("../../dispatcher");
|
||||
var q = require('q');
|
||||
var version = require('../../../package.json').version;
|
||||
var UserSettingsStore = require('../../UserSettingsStore');
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'UserSettings',
|
||||
Phases: {
|
||||
Loading: "loading",
|
||||
Display: "display",
|
||||
|
||||
propTypes: {
|
||||
onClose: React.PropTypes.func
|
||||
},
|
||||
|
||||
getDefaultProps: function() {
|
||||
return {
|
||||
onClose: function() {}
|
||||
};
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
|
@ -32,131 +40,227 @@ module.exports = React.createClass({
|
|||
avatarUrl: null,
|
||||
threePids: [],
|
||||
clientVersion: version,
|
||||
phase: this.Phases.Loading,
|
||||
phase: "UserSettings.LOADING", // LOADING, DISPLAY
|
||||
};
|
||||
},
|
||||
|
||||
componentWillMount: function() {
|
||||
var self = this;
|
||||
var cli = MatrixClientPeg.get();
|
||||
|
||||
var profile_d = cli.getProfileInfo(cli.credentials.userId);
|
||||
var threepid_d = cli.getThreePids();
|
||||
|
||||
q.all([profile_d, threepid_d]).then(
|
||||
function(resps) {
|
||||
self.setState({
|
||||
avatarUrl: resps[0].avatar_url,
|
||||
threepids: resps[1].threepids,
|
||||
phase: self.Phases.Display,
|
||||
});
|
||||
},
|
||||
function(err) { console.err(err); }
|
||||
);
|
||||
this._refreshFromServer();
|
||||
},
|
||||
|
||||
editAvatar: function() {
|
||||
var url = MatrixClientPeg.get().mxcUrlToHttp(this.state.avatarUrl);
|
||||
var ChangeAvatar = sdk.getComponent('settings.ChangeAvatar');
|
||||
var avatarDialog = (
|
||||
<div>
|
||||
<ChangeAvatar initialAvatarUrl={url} />
|
||||
<div className="mx_Dialog_buttons">
|
||||
<button onClick={this.onAvatarDialogCancel}>Cancel</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
this.avatarDialog = Modal.createDialogWithElement(avatarDialog);
|
||||
componentDidMount: function() {
|
||||
this.dispatcherRef = dis.register(this.onAction);
|
||||
this._me = MatrixClientPeg.get().credentials.userId;
|
||||
},
|
||||
|
||||
addEmail: function() {
|
||||
|
||||
componentWillUnmount: function() {
|
||||
dis.unregister(this.dispatcherRef);
|
||||
},
|
||||
|
||||
editDisplayName: function() {
|
||||
this.refs.displayname.edit();
|
||||
_refreshFromServer: function() {
|
||||
var self = this;
|
||||
q.all([
|
||||
UserSettingsStore.loadProfileInfo(), UserSettingsStore.loadThreePids()
|
||||
]).done(function(resps) {
|
||||
self.setState({
|
||||
avatarUrl: resps[0].avatar_url,
|
||||
threepids: resps[1].threepids,
|
||||
phase: "UserSettings.DISPLAY",
|
||||
});
|
||||
}, function(error) {
|
||||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: "Can't load user settings",
|
||||
description: error.toString()
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
changePassword: function() {
|
||||
var ChangePassword = sdk.getComponent('settings.ChangePassword');
|
||||
Modal.createDialog(ChangePassword);
|
||||
onAction: function(payload) {
|
||||
if (payload.action === "notifier_enabled") {
|
||||
this.forceUpdate();
|
||||
}
|
||||
},
|
||||
|
||||
onAvatarSelected: function(ev) {
|
||||
var self = this;
|
||||
var changeAvatar = this.refs.changeAvatar;
|
||||
if (!changeAvatar) {
|
||||
console.error("No ChangeAvatar found to upload image to!");
|
||||
return;
|
||||
}
|
||||
changeAvatar.onFileSelected(ev).done(function() {
|
||||
// dunno if the avatar changed, re-check it.
|
||||
self._refreshFromServer();
|
||||
}, function(err) {
|
||||
var errMsg = (typeof err === "string") ? err : (err.error || "");
|
||||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: "Error",
|
||||
description: "Failed to set avatar. " + errMsg
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
onLogoutClicked: function(ev) {
|
||||
var LogoutPrompt = sdk.getComponent('dialogs.LogoutPrompt');
|
||||
this.logoutModal = Modal.createDialog(LogoutPrompt, {onCancel: this.onLogoutPromptCancel});
|
||||
this.logoutModal = Modal.createDialog(
|
||||
LogoutPrompt, {onCancel: this.onLogoutPromptCancel}
|
||||
);
|
||||
},
|
||||
|
||||
onPasswordChangeError: function(err) {
|
||||
var errMsg = err.error || "";
|
||||
if (err.httpStatus === 403) {
|
||||
errMsg = "Failed to change password. Is your password correct?";
|
||||
}
|
||||
else if (err.httpStatus) {
|
||||
errMsg += ` (HTTP status ${err.httpStatus})`;
|
||||
}
|
||||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: "Error",
|
||||
description: errMsg
|
||||
});
|
||||
},
|
||||
|
||||
onPasswordChanged: function() {
|
||||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: "Success",
|
||||
description: `Your password was successfully changed. You will not
|
||||
receive push notifications on other devices until you
|
||||
log back in to them.`
|
||||
});
|
||||
},
|
||||
|
||||
onLogoutPromptCancel: function() {
|
||||
this.logoutModal.closeDialog();
|
||||
},
|
||||
|
||||
onAvatarDialogCancel: function() {
|
||||
this.avatarDialog.close();
|
||||
onEnableNotificationsChange: function(event) {
|
||||
UserSettingsStore.setEnableNotifications(event.target.checked);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var Loader = sdk.getComponent("elements.Spinner");
|
||||
if (this.state.phase === this.Phases.Loading) {
|
||||
return <Loader />
|
||||
switch (this.state.phase) {
|
||||
case "UserSettings.LOADING":
|
||||
var Loader = sdk.getComponent("elements.Spinner");
|
||||
return (
|
||||
<Loader />
|
||||
);
|
||||
case "UserSettings.DISPLAY":
|
||||
break; // quit the switch to return the common state
|
||||
default:
|
||||
throw new Error("Unknown state.phase => " + this.state.phase);
|
||||
}
|
||||
else if (this.state.phase === this.Phases.Display) {
|
||||
var ChangeDisplayName = sdk.getComponent('settings.ChangeDisplayName');
|
||||
var EnableNotificationsButton = sdk.getComponent('settings.EnableNotificationsButton');
|
||||
return (
|
||||
// can only get here if phase is UserSettings.DISPLAY
|
||||
var RoomHeader = sdk.getComponent('rooms.RoomHeader');
|
||||
var ChangeDisplayName = sdk.getComponent("views.settings.ChangeDisplayName");
|
||||
var ChangePassword = sdk.getComponent("views.settings.ChangePassword");
|
||||
var ChangeAvatar = sdk.getComponent('settings.ChangeAvatar');
|
||||
var avatarUrl = (
|
||||
this.state.avatarUrl ? MatrixClientPeg.get().mxcUrlToHttp(this.state.avatarUrl) : null
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="mx_UserSettings">
|
||||
<div className="mx_UserSettings_User">
|
||||
<h1>User Settings</h1>
|
||||
<hr/>
|
||||
<div className="mx_UserSettings_User_Inner">
|
||||
<div className="mx_UserSettings_Avatar">
|
||||
<div className="mx_UserSettings_Avatar_Text">
|
||||
Profile Photo
|
||||
<RoomHeader simpleHeader="Settings" />
|
||||
|
||||
<h2>Profile</h2>
|
||||
|
||||
<div className="mx_UserSettings_section">
|
||||
<div className="mx_UserSettings_profileTable">
|
||||
<div className="mx_UserSettings_profileTableRow">
|
||||
<div className="mx_UserSettings_profileLabelCell">
|
||||
<label htmlFor="displayName">Display name</label>
|
||||
</div>
|
||||
<div className="mx_UserSettings_Avatar_Edit" onClick={this.editAvatar}>
|
||||
Edit
|
||||
<div className="mx_UserSettings_profileInputCell">
|
||||
<ChangeDisplayName />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mx_UserSettings_DisplayName">
|
||||
<ChangeDisplayName ref="displayname" />
|
||||
<div className="mx_UserSettings_DisplayName_Edit" onClick={this.editDisplayName}>
|
||||
Edit
|
||||
</div>
|
||||
</div>
|
||||
{this.state.threepids.map(function(val, pidIndex) {
|
||||
var id = "email-" + val.address;
|
||||
return (
|
||||
<div className="mx_UserSettings_profileTableRow" key={pidIndex}>
|
||||
<div className="mx_UserSettings_profileLabelCell">
|
||||
<label htmlFor={id}>Email</label>
|
||||
</div>
|
||||
<div className="mx_UserSettings_profileInputCell">
|
||||
<input key={val.address} id={id} value={val.address} disabled />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
||||
<div className="mx_UserSettings_3pids">
|
||||
{this.state.threepids.map(function(val) {
|
||||
return <div key={val.address}>{val.address}</div>;
|
||||
})}
|
||||
</div>
|
||||
|
||||
<div className="mx_UserSettings_Add3pid" onClick={this.addEmail}>
|
||||
Add email
|
||||
<div className="mx_UserSettings_avatarPicker">
|
||||
<ChangeAvatar ref="changeAvatar" initialAvatarUrl={avatarUrl}
|
||||
showUploadSection={false} className="mx_UserSettings_avatarPicker_img"/>
|
||||
<div className="mx_UserSettings_avatarPicker_edit">
|
||||
<label htmlFor="avatarInput">
|
||||
<img src="img/upload.svg"
|
||||
alt="Upload avatar" title="Upload avatar"
|
||||
width="19" height="24" />
|
||||
</label>
|
||||
<input id="avatarInput" type="file" onChange={this.onAvatarSelected}/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mx_UserSettings_Global">
|
||||
<h1>Global Settings</h1>
|
||||
<hr/>
|
||||
<div className="mx_UserSettings_Global_Inner">
|
||||
<div className="mx_UserSettings_ChangePassword" onClick={this.changePassword}>
|
||||
Change Password
|
||||
</div>
|
||||
<div className="mx_UserSettings_ClientVersion">
|
||||
Version {this.state.clientVersion}
|
||||
</div>
|
||||
<div className="mx_UserSettings_EnableNotifications">
|
||||
<EnableNotificationsButton />
|
||||
</div>
|
||||
<div className="mx_UserSettings_Logout">
|
||||
<button onClick={this.onLogoutClicked}>Sign Out</button>
|
||||
<h2>Account</h2>
|
||||
|
||||
<div className="mx_UserSettings_section">
|
||||
<ChangePassword
|
||||
className="mx_UserSettings_accountTable"
|
||||
rowClassName="mx_UserSettings_profileTableRow"
|
||||
rowLabelClassName="mx_UserSettings_profileLabelCell"
|
||||
rowInputClassName="mx_UserSettings_profileInputCell"
|
||||
buttonClassName="mx_UserSettings_button"
|
||||
onError={this.onPasswordChangeError}
|
||||
onFinished={this.onPasswordChanged} />
|
||||
</div>
|
||||
|
||||
<div className="mx_UserSettings_logout">
|
||||
<div className="mx_UserSettings_button" onClick={this.onLogoutClicked}>
|
||||
Log out
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2>Notifications</h2>
|
||||
|
||||
<div className="mx_UserSettings_section">
|
||||
<div className="mx_UserSettings_notifTable">
|
||||
<div className="mx_UserSettings_notifTableRow">
|
||||
<div className="mx_UserSettings_notifInputCell">
|
||||
<input id="enableNotifications"
|
||||
ref="enableNotifications"
|
||||
type="checkbox"
|
||||
checked={ UserSettingsStore.getEnableNotifications() }
|
||||
onChange={ this.onEnableNotificationsChange } />
|
||||
</div>
|
||||
<div className="mx_UserSettings_notifLabelCell">
|
||||
<label htmlFor="enableNotifications">
|
||||
Enable desktop notifications
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2>Advanced</h2>
|
||||
|
||||
<div className="mx_UserSettings_section">
|
||||
<div className="mx_UserSettings_advanced">
|
||||
Logged in as {this._me}
|
||||
</div>
|
||||
<div className="mx_UserSettings_advanced">
|
||||
Version {this.state.clientVersion}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -113,6 +113,10 @@ module.exports = React.createClass({
|
|||
}
|
||||
},
|
||||
|
||||
onBlur: function() {
|
||||
this.cancelEdit();
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var editable_el;
|
||||
|
||||
|
@ -125,7 +129,8 @@ module.exports = React.createClass({
|
|||
} else if (this.state.phase == this.Phases.Edit) {
|
||||
editable_el = (
|
||||
<div>
|
||||
<input type="text" defaultValue={this.state.value} onKeyUp={this.onKeyUp} onFocus={this.onFocus} onBlur={this.onFinish} placeholder={this.props.placeHolder} autoFocus/>
|
||||
<input type="text" defaultValue={this.state.value}
|
||||
onKeyUp={this.onKeyUp} onFocus={this.onFocus} onBlur={this.onBlur} placeholder={this.props.placeHolder} autoFocus/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -73,10 +73,15 @@ module.exports = React.createClass({
|
|||
|
||||
var header;
|
||||
if (this.props.simpleHeader) {
|
||||
var cancel;
|
||||
if (this.props.onCancelClick) {
|
||||
cancel = <img className="mx_RoomHeader_simpleHeaderCancel" src="img/cancel-black.png" onClick={ this.props.onCancelClick } alt="Close" width="18" height="18"/>
|
||||
}
|
||||
header =
|
||||
<div className="mx_RoomHeader_wrapper">
|
||||
<div className="mx_RoomHeader_simpleHeader">
|
||||
{ this.props.simpleHeader }
|
||||
{ cancel }
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
|
|
@ -23,6 +23,9 @@ module.exports = React.createClass({
|
|||
propTypes: {
|
||||
initialAvatarUrl: React.PropTypes.string,
|
||||
room: React.PropTypes.object,
|
||||
// if false, you need to call changeAvatar.onFileSelected yourself.
|
||||
showUploadSection: React.PropTypes.bool,
|
||||
className: React.PropTypes.string
|
||||
},
|
||||
|
||||
Phases: {
|
||||
|
@ -31,6 +34,13 @@ module.exports = React.createClass({
|
|||
Error: "error",
|
||||
},
|
||||
|
||||
getDefaultProps: function() {
|
||||
return {
|
||||
showUploadSection: true,
|
||||
className: "mx_Dialog_content" // FIXME - shouldn't be this by default
|
||||
};
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
return {
|
||||
avatarUrl: this.props.initialAvatarUrl,
|
||||
|
@ -55,7 +65,7 @@ module.exports = React.createClass({
|
|||
phase: this.Phases.Uploading
|
||||
});
|
||||
var self = this;
|
||||
MatrixClientPeg.get().uploadContent(file).then(function(url) {
|
||||
var httpPromise = MatrixClientPeg.get().uploadContent(file).then(function(url) {
|
||||
newUrl = url;
|
||||
if (self.props.room) {
|
||||
return MatrixClientPeg.get().sendStateEvent(
|
||||
|
@ -67,7 +77,9 @@ module.exports = React.createClass({
|
|||
} else {
|
||||
return MatrixClientPeg.get().setAvatarUrl(url);
|
||||
}
|
||||
}).done(function() {
|
||||
});
|
||||
|
||||
httpPromise.done(function() {
|
||||
self.setState({
|
||||
phase: self.Phases.Display,
|
||||
avatarUrl: MatrixClientPeg.get().mxcUrlToHttp(newUrl)
|
||||
|
@ -78,11 +90,13 @@ module.exports = React.createClass({
|
|||
});
|
||||
self.onError(error);
|
||||
});
|
||||
|
||||
return httpPromise;
|
||||
},
|
||||
|
||||
onFileSelected: function(ev) {
|
||||
this.avatarSet = true;
|
||||
this.setAvatarFromFile(ev.target.files[0]);
|
||||
return this.setAvatarFromFile(ev.target.files[0]);
|
||||
},
|
||||
|
||||
onError: function(error) {
|
||||
|
@ -106,19 +120,26 @@ module.exports = React.createClass({
|
|||
avatarImg = <img src={this.state.avatarUrl} style={style} />;
|
||||
}
|
||||
|
||||
var uploadSection;
|
||||
if (this.props.showUploadSection) {
|
||||
uploadSection = (
|
||||
<div className={this.props.className}>
|
||||
Upload new:
|
||||
<input type="file" onChange={this.onFileSelected}/>
|
||||
{this.state.errorText}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
switch (this.state.phase) {
|
||||
case this.Phases.Display:
|
||||
case this.Phases.Error:
|
||||
return (
|
||||
<div>
|
||||
<div className="mx_Dialog_content">
|
||||
<div className={this.props.className}>
|
||||
{avatarImg}
|
||||
</div>
|
||||
<div className="mx_Dialog_content">
|
||||
Upload new:
|
||||
<input type="file" onChange={this.onFileSelected}/>
|
||||
{this.state.errorText}
|
||||
</div>
|
||||
{uploadSection}
|
||||
</div>
|
||||
);
|
||||
case this.Phases.Uploading:
|
||||
|
|
|
@ -98,7 +98,9 @@ module.exports = React.createClass({
|
|||
} else {
|
||||
var EditableText = sdk.getComponent('elements.EditableText');
|
||||
return (
|
||||
<EditableText ref="displayname_edit" initialValue={this.state.displayName} label="Click to set display name." onValueChanged={this.onValueChanged}/>
|
||||
<EditableText ref="displayname_edit" initialValue={this.state.displayName}
|
||||
label="Click to set display name."
|
||||
onValueChanged={this.onValueChanged} />
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,30 +18,47 @@ limitations under the License.
|
|||
|
||||
var React = require('react');
|
||||
var MatrixClientPeg = require("../../../MatrixClientPeg");
|
||||
var sdk = require("../../../index");
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'ChangePassword',
|
||||
propTypes: {
|
||||
onFinished: React.PropTypes.func,
|
||||
onError: React.PropTypes.func,
|
||||
onCheckPassword: React.PropTypes.func,
|
||||
rowClassName: React.PropTypes.string,
|
||||
rowLabelClassName: React.PropTypes.string,
|
||||
rowInputClassName: React.PropTypes.string,
|
||||
buttonClassName: React.PropTypes.string
|
||||
},
|
||||
|
||||
Phases: {
|
||||
Edit: "edit",
|
||||
Uploading: "uploading",
|
||||
Error: "error",
|
||||
Success: "Success"
|
||||
Error: "error"
|
||||
},
|
||||
|
||||
getDefaultProps: function() {
|
||||
return {
|
||||
onFinished: function() {},
|
||||
onError: function() {},
|
||||
onCheckPassword: function(oldPass, newPass, confirmPass) {
|
||||
if (newPass !== confirmPass) {
|
||||
return {
|
||||
error: "New passwords don't match."
|
||||
};
|
||||
} else if (!newPass || newPass.length === 0) {
|
||||
return {
|
||||
error: "Passwords can't be empty"
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
return {
|
||||
phase: this.Phases.Edit,
|
||||
errorString: ''
|
||||
phase: this.Phases.Edit
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -55,60 +72,72 @@ module.exports = React.createClass({
|
|||
};
|
||||
|
||||
this.setState({
|
||||
phase: this.Phases.Uploading,
|
||||
errorString: '',
|
||||
})
|
||||
|
||||
var d = cli.setPassword(authDict, new_password);
|
||||
phase: this.Phases.Uploading
|
||||
});
|
||||
|
||||
var self = this;
|
||||
d.then(function() {
|
||||
self.setState({
|
||||
phase: self.Phases.Success,
|
||||
errorString: '',
|
||||
})
|
||||
cli.setPassword(authDict, new_password).then(function() {
|
||||
self.props.onFinished();
|
||||
}, function(err) {
|
||||
self.props.onError(err);
|
||||
}).finally(function() {
|
||||
self.setState({
|
||||
phase: self.Phases.Error,
|
||||
errorString: err.toString()
|
||||
})
|
||||
});
|
||||
phase: self.Phases.Edit
|
||||
});
|
||||
}).done();
|
||||
},
|
||||
|
||||
onClickChange: function() {
|
||||
var old_password = this.refs.old_input.value;
|
||||
var new_password = this.refs.new_input.value;
|
||||
var confirm_password = this.refs.confirm_input.value;
|
||||
if (new_password != confirm_password) {
|
||||
this.setState({
|
||||
state: this.Phases.Error,
|
||||
errorString: "Passwords don't match"
|
||||
});
|
||||
} else if (new_password == '' || old_password == '') {
|
||||
this.setState({
|
||||
state: this.Phases.Error,
|
||||
errorString: "Passwords can't be empty"
|
||||
});
|
||||
} else {
|
||||
var err = this.props.onCheckPassword(
|
||||
old_password, new_password, confirm_password
|
||||
);
|
||||
if (err) {
|
||||
this.props.onError(err);
|
||||
}
|
||||
else {
|
||||
this.changePassword(old_password, new_password);
|
||||
}
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var rowClassName = this.props.rowClassName;
|
||||
var rowLabelClassName = this.props.rowLabelClassName;
|
||||
var rowInputClassName = this.props.rowInputClassName
|
||||
var buttonClassName = this.props.buttonClassName;
|
||||
|
||||
switch (this.state.phase) {
|
||||
case this.Phases.Edit:
|
||||
case this.Phases.Error:
|
||||
return (
|
||||
<div>
|
||||
<div className="mx_Dialog_content">
|
||||
<div>{this.state.errorString}</div>
|
||||
<div><label>Old password <input type="password" ref="old_input"/></label></div>
|
||||
<div><label>New password <input type="password" ref="new_input"/></label></div>
|
||||
<div><label>Confirm password <input type="password" ref="confirm_input"/></label></div>
|
||||
<div className={this.props.className}>
|
||||
<div className={rowClassName}>
|
||||
<div className={rowLabelClassName}>
|
||||
<label htmlFor="passwordold">Current password</label>
|
||||
</div>
|
||||
<div className={rowInputClassName}>
|
||||
<input id="passwordold" type="password" ref="old_input" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="mx_Dialog_buttons">
|
||||
<button onClick={this.onClickChange}>Change Password</button>
|
||||
<button onClick={this.props.onFinished}>Cancel</button>
|
||||
<div className={rowClassName}>
|
||||
<div className={rowLabelClassName}>
|
||||
<label htmlFor="password1">New password</label>
|
||||
</div>
|
||||
<div className={rowInputClassName}>
|
||||
<input id="password1" type="password" ref="new_input" />
|
||||
</div>
|
||||
</div>
|
||||
<div className={rowClassName}>
|
||||
<div className={rowLabelClassName}>
|
||||
<label htmlFor="password2">Confirm password</label>
|
||||
</div>
|
||||
<div className={rowInputClassName}>
|
||||
<input id="password2" type="password" ref="confirm_input" />
|
||||
</div>
|
||||
</div>
|
||||
<div className={buttonClassName} onClick={this.onClickChange}>
|
||||
Change Password
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -119,17 +148,6 @@ module.exports = React.createClass({
|
|||
<Loader />
|
||||
</div>
|
||||
);
|
||||
case this.Phases.Success:
|
||||
return (
|
||||
<div>
|
||||
<div className="mx_Dialog_content">
|
||||
Success!
|
||||
</div>
|
||||
<div className="mx_Dialog_buttons">
|
||||
<button onClick={this.props.onFinished}>Ok</button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue