adds timezone

This commit is contained in:
Toni Dezman 2017-08-16 13:41:55 +02:00
parent 52b1603b92
commit 522262f9fe
11 changed files with 195 additions and 5 deletions

View file

@ -12,3 +12,4 @@ 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";
export const CHANGE_CURRENT_USER_TIMEZONE = "CHANGE_CURRENT_USER_TIMEZONE";

View file

@ -6,7 +6,8 @@ import {
CHANGE_CURRENT_USER_INITIALS,
CHANGE_CURRENT_USER_EMAIL,
CHANGE_CURRENT_USER_PASSWORD,
CHANGE_CURRENT_USER_AVATAR
CHANGE_CURRENT_USER_AVATAR,
CHANGE_CURRENT_USER_TIMEZONE
} from "../../app/action_types";
function addCurrentUser(data) {
@ -63,3 +64,10 @@ export function changeAvatar(avatarSrc) {
payload: avatarSrc
};
}
export function changeTimezone(timezone) {
return {
type: CHANGE_CURRENT_USER_TIMEZONE,
payload: timezone
};
}

View file

@ -4,7 +4,8 @@ import {
CHANGE_CURRENT_USER_INITIALS,
CHANGE_CURRENT_USER_EMAIL,
CHANGE_CURRENT_USER_PASSWORD,
CHANGE_CURRENT_USER_AVATAR
CHANGE_CURRENT_USER_AVATAR,
CHANGE_CURRENT_USER_TIMEZONE
} from "../../app/action_types";
export function currentUser(
@ -14,7 +15,8 @@ export function currentUser(
initials: "",
email: "",
avatarPath: "",
avatarThumbPath: ""
avatarThumbPath: "",
timezone: ""
},
action
) {
@ -33,6 +35,8 @@ export function currentUser(
return state;
case CHANGE_CURRENT_USER_AVATAR:
return Object.assign({}, state, { avatar: action.payload });
case CHANGE_CURRENT_USER_TIMEZONE:
return Object.assign({}, state, { timezone: action.payload });
default:
return state;
}

View file

@ -6,6 +6,7 @@ const AvatarWrapper = styled.div`
width: 100px;
height: 100px;
position: relative;
cursor: pointer;
`;
const EditAvatar = styled.span`
position: absolute;

View file

@ -0,0 +1,61 @@
import React, { Component } from "react";
import PropType from "prop-types";
import { Button } from "react-bootstrap";
import TimezonePicker from "react-bootstrap-timezone-picker";
import "react-bootstrap-timezone-picker/dist/react-bootstrap-timezone-picker.min.css";
class InputTimezone extends Component {
constructor(props) {
super(props);
this.state = {
value: props.inputValue
};
this.handleChange = this.handleChange.bind(this);
this.handleUpdate = this.handleUpdate.bind(this);
}
handleChange(timezone) {
this.setState({ value: timezone });
}
handleUpdate() {
if (this.state.value !== "") {
this.props.saveData(this.state.value);
}
this.props.disableEdit();
}
render() {
return (
<div>
<h4>
{this.props.labelValue}
</h4>
<TimezonePicker
absolute
defaultValue="Europe/London"
value={this.props.inputValue}
placeholder="Select timezone..."
onChange={this.handleChange}
className="time-zone-container"
/>
<Button bsStyle="primary" onClick={this.props.disableEdit}>
Cancel
</Button>
<Button bsStyle="default" onClick={this.handleUpdate}>
Update
</Button>
</div>
);
}
}
InputTimezone.propTypes = {
labelValue: PropType.string.isRequired,
inputValue: PropType.string.isRequired,
disableEdit: PropType.func.isRequired,
saveData: PropType.func.isRequired
};
export default InputTimezone;

View file

@ -15,7 +15,7 @@ class MyStatistics extends Component {
<div>
<MyStatisticsBox
typeLength={stats.number_of_teams}
typeText="Team"
typeText="Teams"
/>
<MyStatisticsBox
typeLength={stats.number_of_projects}

View file

@ -0,0 +1,74 @@
import React, { Component } from "react";
import { connect } from "react-redux";
import PropTypes from "prop-types";
import InputDisabled from "./InputDisabled";
import InputTimezone from "./InputTimezone";
import { changeTimezone } from "../../../shared/actions/UsersActions";
class SettingsPreferences extends Component {
constructor(props) {
super(props);
this.state = {
isTimeZoneEditable: true
};
}
toggleIsEditable(fieldNameEnabled) {
const editableState = this.state[fieldNameEnabled];
this.setState({ [fieldNameEnabled]: !editableState });
}
render() {
const isTimeZoneEditable = "isTimeZoneEditable";
let timezoneField;
if (this.state.isTimeZoneEditable) {
timezoneField = (
<InputTimezone
labelValue="Time zone"
inputValue={this.props.timezone}
disableEdit={() => this.toggleIsEditable(isTimeZoneEditable)}
saveData={timeZone => this.props.changeTimezone(timeZone)}
/>
);
} else {
timezoneField = (
<InputDisabled
labelValue="Time zone"
inputValue={this.props.timezone}
inputType="text"
enableEdit={() => this.toggleIsEditable(isTimeZoneEditable)}
/>
);
}
return (
<div className="col-xs-12 col-sm-7">
{timezoneField}
<small>
Time zone setting affects all time & date fields throughout
application.
</small>
</div>
);
}
}
SettingsPreferences.propTypes = {
timezone: PropTypes.string.isRequired,
changeTimezone: PropTypes.func.isRequired
};
const mapStateToProps = state => state.current_user;
const mapDispatchToProps = dispatch => ({
changeTimezone(timezone) {
dispatch(changeTimezone(timezone));
}
});
export default connect(mapStateToProps, mapDispatchToProps)(
SettingsPreferences
);

View file

@ -3,6 +3,27 @@
body {
background-color: $color-concrete;
color: $color-emperor;
font-family: "Open Sans",Arial,Helvetica,sans-serif;
font-family: "Open Sans", Arial, Helvetica, sans-serif;
font-size: 13px;
}
.time-zone-container {
background: $color-white;
ul {
width: 100%;
height: 70vh;
overflow: auto;
position: relative;
padding-left: 5px;
}
li {
list-style-type: none;
line-height: 1.4 em;
font-size: 1.5 em;
cursor: pointer;
&:hover {
background: $color-gainsboro;
}
}
}

View file

@ -6,4 +6,5 @@ json.user do
json.avatarPath avatar_path(user, :icon_small)
json.avatarThumbPath avatar_path(user, :thumb)
json.statistics user.statistics
json.timezone user.time_zone
end

17
package-lock.json generated
View file

@ -7687,6 +7687,15 @@
"warning": "3.0.0"
}
},
"react-bootstrap-timezone-picker": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/react-bootstrap-timezone-picker/-/react-bootstrap-timezone-picker-1.0.11.tgz",
"integrity": "sha1-IQooSuNcCjJDVHuupGV9eKv5aoY=",
"requires": {
"classnames": "2.2.5",
"prop-types": "15.5.10"
}
},
"react-dom": {
"version": "15.6.1",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-15.6.1.tgz",
@ -7800,6 +7809,14 @@
"react-router": "4.1.2"
}
},
"react-timezone": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/react-timezone/-/react-timezone-0.2.0.tgz",
"integrity": "sha1-AxttcAsV623Zd+MmsF/pCAuKK20=",
"requires": {
"classnames": "2.2.5"
}
},
"read-cache": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",

View file

@ -62,12 +62,14 @@
"rails-erb-loader": "^5.0.2",
"react": "^15.6.1",
"react-bootstrap": "^0.31.1",
"react-bootstrap-timezone-picker": "^1.0.11",
"react-dom": "^15.6.1",
"react-intl": "^2.3.0",
"react-intl-redux": "^0.6.0",
"react-redux": "^5.0.5",
"react-router-bootstrap": "^0.24.2",
"react-router-dom": "^4.1.2",
"react-timezone": "^0.2.0",
"redux": "^3.7.2",
"redux-thunk": "^2.2.0",
"resolve-url-loader": "^2.1.0",