logic for MyProfile component is finished

This commit is contained in:
Toni Dezman 2017-08-14 13:31:26 +02:00
parent a3d126b073
commit 086be89a5d
10 changed files with 10079 additions and 19 deletions

View file

@ -10,3 +10,5 @@ export const SET_CURRENT_USER = "SET_CURRENT_USER";
export const CHANGE_CURRENT_USER_FULL_NAME = "CHANGE_CURRENT_USER_FULL_NAME";
export const CHANGE_CURRENT_USER_INITIALS = "CHANGE_CURRENT_USER_INITIALS";
export const CHANGE_CURRENT_USER_EMAIL = "CHANGE_CURRENT_USER_EMAIL";
export const CHANGE_CURRENT_USER_PASSWORD = "CHANGE_CURRENT_USER_PASSWORD";
export const CHANGE_CURRENT_USER_AVATAR = "CHANGE_CURRENT_USER_AVATAR";

View file

@ -21,3 +21,8 @@ export const RELEASE_NOTES_LINK = "http://scinote.net/docs/release-notes/";
export const PREMIUM_LINK = "http://scinote.net/premium/";
export const CONTACT_US_LINK =
"http://scinote.net/story-of-scinote/#contact-scinote";
// settings
export const SETTINGS_ACCOUNT_PROFILE = "/settings/account/profile";
export const SETTINGS_ACCOUNT_PREFERENCES = "/settings/account/preferences";
export const SETTINGS_TEAMS = "/settings/teams";

View file

@ -4,7 +4,9 @@ import {
SET_CURRENT_USER,
CHANGE_CURRENT_USER_FULL_NAME,
CHANGE_CURRENT_USER_INITIALS,
CHANGE_CURRENT_USER_EMAIL
CHANGE_CURRENT_USER_EMAIL,
CHANGE_CURRENT_USER_PASSWORD,
CHANGE_CURRENT_USER_AVATAR
} from "../../app/action_types";
function addCurrentUser(data) {
@ -47,3 +49,17 @@ export function changeEmail(email) {
payload: email
};
}
export function changePassword(password) {
return {
type: CHANGE_CURRENT_USER_PASSWORD,
payload: password
};
}
export function changeAvatar(avatarSrc) {
return {
type: CHANGE_CURRENT_USER_AVATAR,
payload: avatarSrc
};
}

View file

@ -2,7 +2,9 @@ import {
SET_CURRENT_USER,
CHANGE_CURRENT_USER_FULL_NAME,
CHANGE_CURRENT_USER_INITIALS,
CHANGE_CURRENT_USER_EMAIL
CHANGE_CURRENT_USER_EMAIL,
CHANGE_CURRENT_USER_PASSWORD,
CHANGE_CURRENT_USER_AVATAR
} from "../../app/action_types";
export function currentUser(
@ -25,6 +27,12 @@ export function currentUser(
return Object.assign({}, state, { initials: action.payload });
case CHANGE_CURRENT_USER_EMAIL:
return Object.assign({}, state, { email: action.payload });
case CHANGE_CURRENT_USER_PASSWORD:
console.log("handle sending password to the server");
// return Object.assign({}, state, { password: action.payload });
return state;
case CHANGE_CURRENT_USER_AVATAR:
return Object.assign({}, state, { avatar: action.payload });
default:
return state;
}

View file

@ -1,10 +1,29 @@
import React from "react";
import { string } from "prop-types";
import PropTypes, { string } from "prop-types";
import styled from "styled-components";
const Avatar = props => <img src={props.imgSource} alt="default avatar" />;
const AvatarWrapper = styled.div`
width: 100px;
height: 100px;
position: relative;
`;
const EditAvatar = styled.span`
position: absolute;
left: 0;
bottom: 0;
width: 100%;
background-color: silver;
`;
const Avatar = props =>
<AvatarWrapper onClick={props.enableEdit}>
<img src={props.imgSource} alt="default avatar" />
<EditAvatar>Edit Avatar</EditAvatar>
</AvatarWrapper>;
Avatar.propTypes = {
imgSource: string.isRequired
imgSource: string.isRequired,
enableEdit: PropTypes.func.isRequired
};
export default Avatar;

View file

@ -1,16 +1,32 @@
import React, { Component } from "react";
import PropTypes from "prop-types";
import styled from "styled-components";
import { FormGroup, FormControl, ControlLabel, Button } from "react-bootstrap";
const StyledInputEnabled = styled.div`
border: 1px solid black;
padding: 10px;
`;
const ErrorMsg = styled.div`color: red;`;
class InputEnabled extends Component {
constructor(props) {
super(props);
this.state = {
value: this.props.inputValue
};
if (props.inputType === "password") {
this.state = {
value: "",
value2: ""
};
} else {
this.state = {
value: this.props.inputValue
};
}
this.handleChange = this.handleChange.bind(this);
this.handleChange2 = this.handleChange2.bind(this);
this.handleUpdate = this.handleUpdate.bind(this);
}
@ -18,6 +34,10 @@ class InputEnabled extends Component {
this.setState({ value: event.target.value });
}
handleChange2(event) {
this.setState({ value2: event.target.value });
}
handleSubmit(event) {
event.preventDefault();
}
@ -27,19 +47,74 @@ class InputEnabled extends Component {
this.props.disableEdit();
}
confirmationField() {
let inputs;
const type = this.props.inputType;
if (type === "email" || type === "password") {
inputs = (
<div>
<p>
Current password (we need your current password to confirm your
changes)
</p>
<FormControl type="password" />
</div>
);
}
return inputs;
}
errorMsg() {
return this.state.value !== this.state.value2
? <ErrorMsg>Passwords do not match!</ErrorMsg>
: "";
}
inputField() {
let input;
if (this.props.inputType === "password") {
input = (
<div>
<FormControl
type={this.props.inputType}
value={this.state.value}
onChange={this.handleChange}
/>
<p>New password confirmation</p>
<FormControl
type={this.props.inputType}
value={this.state.value2}
onChange={this.handleChange2}
/>
{this.errorMsg()}
</div>
);
} else {
input = (
<FormControl
type={this.props.inputType}
value={this.state.value}
onChange={this.handleChange}
/>
);
}
return input;
}
render() {
return (
<div>
<StyledInputEnabled>
<form onSubmit={this.handleSubmit}>
<FormGroup>
{this.confirmationField()}
<ControlLabel>
{this.props.labelValue}
</ControlLabel>
<FormControl
type={this.props.inputType}
value={this.state.value}
onChange={this.handleChange}
/>
{this.inputField()}
<Button bsStyle="primary" onClick={this.props.disableEdit}>
Cancel
</Button>
@ -48,7 +123,7 @@ class InputEnabled extends Component {
</Button>
</FormGroup>
</form>
</div>
</StyledInputEnabled>
);
}
}

View file

@ -0,0 +1,39 @@
import React, { Component } from "react";
import { LinkContainer } from "react-router-bootstrap";
import { Nav, NavItem } from "react-bootstrap";
import { SETTINGS_ACCOUNT_PROFILE, SETTINGS_TEAMS } from "../../../app/routes";
export default class MainNav extends Component {
constructor(props) {
super(props);
this.state = {
active: "1"
};
this.handleSelect = this.handleSelect.bind(this);
}
handleSelect(eventKey) {
event.preventDefault();
this.setState({ active: eventKey });
}
render() {
return (
<div>
<Nav bsStyle="tabs" activeKey="1" onSelect={this.handleSelect}>
<LinkContainer
active={this.state.active === "1"}
to={SETTINGS_ACCOUNT_PROFILE}
>
<NavItem eventKey="1">Account</NavItem>
</LinkContainer>
<LinkContainer to={SETTINGS_TEAMS} active={this.state.active === "2"}>
<NavItem eventKey="2">Team</NavItem>
</LinkContainer>
</Nav>
</div>
);
}
}

View file

@ -9,7 +9,9 @@ import InputEnabled from "./InputEnabled";
import {
changeFullName,
changeInitials,
changeEmail
changeEmail,
changePassword,
changeAvatar
} from "../../../shared/actions/UsersActions";
class MyProfile extends Component {
@ -19,7 +21,9 @@ class MyProfile extends Component {
this.state = {
isFullNameEditable: false,
areInitialsEditable: false,
isEmailEditable: false
isEmailEditable: false,
isPasswordEditable: false,
isAvatarEditable: false
};
this.toggleIsEditable = this.toggleIsEditable.bind(this);
@ -34,9 +38,53 @@ class MyProfile extends Component {
const areInitialsEditable = "areInitialsEditable";
const isFullNameEditable = "isFullNameEditable";
const isEmailEditable = "isEmailEditable";
const isPasswordEditable = "isPasswordEditable";
const isAvatarEditable = "isAvatarEditable";
let fullNameField;
let initialsField;
let emailField;
let passwordField;
let avatarField;
if (this.state.isAvatarEditable) {
avatarField = (
<InputEnabled
labelValue="Avatar"
inputType="file"
inputValue=""
disableEdit={() => this.toggleIsEditable(isAvatarEditable)}
saveData={avatarSrc => this.props.changeAvatar(avatarSrc)}
/>
);
} else {
avatarField = (
<Avatar
imgSource={this.props.avatarThumbPath}
enableEdit={() => this.toggleIsEditable(isAvatarEditable)}
/>
);
}
if (this.state.isPasswordEditable) {
passwordField = (
<InputEnabled
labelValue="Change password"
inputType="password"
inputValue=""
disableEdit={() => this.toggleIsEditable(isPasswordEditable)}
saveData={newPassword => this.props.changePassword(newPassword)}
/>
);
} else {
passwordField = (
<InputDisabled
labelValue="Change password"
inputType="password"
inputValue=""
enableEdit={() => this.toggleIsEditable(isPasswordEditable)}
/>
);
}
if (this.state.isEmailEditable) {
emailField = (
@ -105,10 +153,11 @@ class MyProfile extends Component {
<div>
<h2>My Profile</h2>
<h4>Avatar</h4>
<Avatar imgSource={this.props.avatarThumbPath} />
{avatarField}
{fullNameField}
{initialsField}
{emailField}
{passwordField}
</div>
);
}
@ -121,7 +170,9 @@ MyProfile.propTypes = {
email: PropTypes.string.isRequired,
changeFullName: PropTypes.func.isRequired,
changeInitials: PropTypes.func.isRequired,
changeEmail: PropTypes.func.isRequired
changeEmail: PropTypes.func.isRequired,
changePassword: PropTypes.func.isRequired,
changeAvatar: PropTypes.func.isRequired
};
const mapStateToProps = state => state.current_user;
@ -134,6 +185,12 @@ const mapDispatchToProps = dispatch => ({
},
changeEmail(email) {
dispatch(changeEmail(email));
},
changePassword(password) {
dispatch(changePassword(password));
},
changeAvatar(avatarSrc) {
dispatch(changeAvatar(avatarSrc));
}
});

View file

@ -0,0 +1,32 @@
import React, { Component } from "react";
import { Nav, NavItem } from "react-bootstrap";
import { LinkContainer } from "react-router-bootstrap";
import {
SETTINGS_ACCOUNT_PROFILE,
SETTINGS_ACCOUNT_PREFERENCES
} from "../../../app/routes";
class SettingsAccountLeftTab extends Component {
constructor(props) {
super(props);
this.handleSelect = this.handleSelect.bind(this);
}
handleSelect(selectedKey) {}
render() {
return (
<Nav bsStyle="pills" stacked activeKey={1} onSelect={this.handleSelect}>
<LinkContainer to={SETTINGS_ACCOUNT_PROFILE}>
<NavItem eventKey={1}>Profile</NavItem>
</LinkContainer>
<LinkContainer to={SETTINGS_ACCOUNT_PREFERENCES}>
<NavItem eventKey={2}>Preferences</NavItem>
</LinkContainer>
</Nav>
);
}
}
export default SettingsAccountLeftTab;

9807
package-lock.json generated Normal file

File diff suppressed because it is too large Load diff