mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2025-09-06 13:14:29 +08:00
adds i18n and 404 page
This commit is contained in:
parent
42d5e67581
commit
1dfd7a0cee
15 changed files with 137 additions and 47 deletions
|
@ -1,11 +1,53 @@
|
|||
export default {
|
||||
"en-US": {
|
||||
general: {
|
||||
close: "Close"
|
||||
close: "Close",
|
||||
cancel: "Cancel",
|
||||
update: "Update",
|
||||
edit: "Edit",
|
||||
loading: "Loading ..."
|
||||
},
|
||||
navbar: {
|
||||
page_title: "sciNote"
|
||||
},
|
||||
settings_page: {
|
||||
account: "Account",
|
||||
team: "Team",
|
||||
avatar: "Avatar",
|
||||
edit_avatar: "Edit Avatar",
|
||||
change: "Change",
|
||||
change_password: "Change Password",
|
||||
new_email: "New email",
|
||||
initials: "Initials",
|
||||
full_name: "Full name",
|
||||
my_profile: "My Profile",
|
||||
my_statistics: "My Statistics",
|
||||
teams: "Teams",
|
||||
project: "Project",
|
||||
projects: "Projects",
|
||||
experiment: "Experiment",
|
||||
experiments: "Experiments",
|
||||
protocol: "Protocol",
|
||||
protocols: "Protocols",
|
||||
time_zone: "Time zone",
|
||||
time_zone_warning:
|
||||
"Time zone setting affects all time & date fields throughout application.",
|
||||
profile: "Profile",
|
||||
preferences: "Preferences",
|
||||
assignement: "Assignement",
|
||||
assignement_msg:
|
||||
"Assignment notifications appear whenever you get assigned to a team, project, task.",
|
||||
recent_changes: "Recent changes",
|
||||
recent_changes_msg:
|
||||
"Recent changes notifications appear whenever there is a change on a task you are assigned to.",
|
||||
system_message: "System message",
|
||||
system_message_msg:
|
||||
"System message notifications are specifically sent by site maintainers to notify all users about a system update.",
|
||||
show_in_scinote: "Show in sciNote",
|
||||
notify_me_via_email: "Notify me via email",
|
||||
no: "No",
|
||||
yes: "Yes"
|
||||
},
|
||||
activities: {
|
||||
modal_title: "Activities",
|
||||
no_data: "No Data",
|
||||
|
|
5
app/javascript/packs/shared/404/NotFound.jsx
Normal file
5
app/javascript/packs/shared/404/NotFound.jsx
Normal file
|
@ -0,0 +1,5 @@
|
|||
import React from "react";
|
||||
|
||||
const NotFound = () => <h1>404 Not found</h1>;
|
||||
|
||||
export default NotFound;
|
|
@ -1,6 +1,7 @@
|
|||
import React, { Component } from "react";
|
||||
import { LinkContainer } from "react-router-bootstrap";
|
||||
import { Nav, NavItem } from "react-bootstrap";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
|
||||
import { SETTINGS_ACCOUNT_PROFILE, SETTINGS_TEAMS } from "../../../app/routes";
|
||||
|
||||
|
@ -27,10 +28,14 @@ export default class MainNav extends Component {
|
|||
active={this.state.active === "1"}
|
||||
to={SETTINGS_ACCOUNT_PROFILE}
|
||||
>
|
||||
<NavItem eventKey="1">Account</NavItem>
|
||||
<NavItem eventKey="1">
|
||||
<FormattedMessage id="settings_page.account" />
|
||||
</NavItem>
|
||||
</LinkContainer>
|
||||
<LinkContainer to={SETTINGS_TEAMS} active={this.state.active === "2"}>
|
||||
<NavItem eventKey="2">Team</NavItem>
|
||||
<NavItem eventKey="2">
|
||||
<FormattedMessage id="settings_page.team" />
|
||||
</NavItem>
|
||||
</LinkContainer>
|
||||
</Nav>
|
||||
</div>
|
||||
|
|
|
@ -2,6 +2,7 @@ import React from "react";
|
|||
import { string, func } from "prop-types";
|
||||
import { FormGroup, FormControl, ControlLabel, Button } from "react-bootstrap";
|
||||
import styled from "styled-components";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
|
||||
const Wrapper = styled.div`margin-top: 19px;`;
|
||||
|
||||
|
@ -21,7 +22,7 @@ const InputDisabled = props =>
|
|||
<form>
|
||||
<FormGroup>
|
||||
<ControlLabel>
|
||||
{props.labelValue}
|
||||
<FormattedMessage id={props.labelTitle} />
|
||||
</ControlLabel>
|
||||
<FormGroup>
|
||||
<MyFormControl
|
||||
|
@ -30,7 +31,7 @@ const InputDisabled = props =>
|
|||
disabled
|
||||
/>
|
||||
<MyButton bsStyle="default" onClick={props.enableEdit}>
|
||||
Edit
|
||||
<FormattedMessage id="general.edit" />
|
||||
</MyButton>
|
||||
</FormGroup>
|
||||
</FormGroup>
|
||||
|
@ -38,7 +39,7 @@ const InputDisabled = props =>
|
|||
</Wrapper>;
|
||||
|
||||
InputDisabled.propTypes = {
|
||||
labelValue: string.isRequired,
|
||||
labelTitle: string.isRequired,
|
||||
inputType: string.isRequired,
|
||||
inputValue: string.isRequired,
|
||||
enableEdit: func.isRequired
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import React, { Component } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import styled from "styled-components";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
import { FormGroup, FormControl, ControlLabel, Button } from "react-bootstrap";
|
||||
|
||||
import {
|
||||
|
@ -131,7 +132,8 @@ class InputEnabled extends Component {
|
|||
<form onSubmit={this.handleSubmit}>
|
||||
<FormGroup>
|
||||
<h4>
|
||||
Change {this.props.labelValue.toLowerCase()}
|
||||
<FormattedMessage id="settings_page.change" />{" "}
|
||||
<FormattedMessage id={this.props.labelTitle} />
|
||||
</h4>
|
||||
{this.confirmationField()}
|
||||
<ControlLabel>
|
||||
|
@ -139,10 +141,10 @@ class InputEnabled extends Component {
|
|||
</ControlLabel>
|
||||
{this.inputField()}
|
||||
<Button bsStyle="primary" onClick={this.props.disableEdit}>
|
||||
Cancel
|
||||
<FormattedMessage id="general.cancel" />
|
||||
</Button>
|
||||
<Button bsStyle="default" onClick={this.handleUpdate}>
|
||||
Update
|
||||
<FormattedMessage id="general.update" />
|
||||
</Button>
|
||||
</FormGroup>
|
||||
</form>
|
||||
|
@ -156,7 +158,8 @@ InputEnabled.propTypes = {
|
|||
labelValue: PropTypes.string.isRequired,
|
||||
inputValue: PropTypes.string.isRequired,
|
||||
disableEdit: PropTypes.func.isRequired,
|
||||
saveData: PropTypes.func.isRequired
|
||||
saveData: PropTypes.func.isRequired,
|
||||
labelTitle: PropTypes.string.isRequired
|
||||
};
|
||||
|
||||
export default InputEnabled;
|
||||
|
|
|
@ -2,6 +2,7 @@ import React, { Component } from "react";
|
|||
import { Nav, NavItem } from "react-bootstrap";
|
||||
import { LinkContainer } from "react-router-bootstrap";
|
||||
import styled from "styled-components";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
|
||||
import {
|
||||
SETTINGS_ACCOUNT_PROFILE,
|
||||
|
@ -46,10 +47,14 @@ const MyLinkContainer = styled(LinkContainer)`
|
|||
const SettingsLeftTab = () =>
|
||||
<Nav bsStyle="pills" stacked activeKey={1}>
|
||||
<MyLinkContainer to={SETTINGS_ACCOUNT_PROFILE}>
|
||||
<NavItem eventKey={1}>Profile</NavItem>
|
||||
<NavItem eventKey={1}>
|
||||
<FormattedMessage id="settings_page.profile" />
|
||||
</NavItem>
|
||||
</MyLinkContainer>
|
||||
<MyLinkContainer to={SETTINGS_ACCOUNT_PREFERENCES}>
|
||||
<NavItem eventKey={2}>Preferences</NavItem>
|
||||
<NavItem eventKey={2}>
|
||||
<FormattedMessage id="settings_page.preferences" />
|
||||
</NavItem>
|
||||
</MyLinkContainer>
|
||||
</Nav>;
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ import { Button } from "react-bootstrap";
|
|||
import styled from "styled-components";
|
||||
import TimezonePicker from "react-bootstrap-timezone-picker";
|
||||
import "react-bootstrap-timezone-picker/dist/react-bootstrap-timezone-picker.min.css";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
|
||||
import {
|
||||
BORDER_LIGHT_COLOR,
|
||||
|
@ -72,8 +73,7 @@ class InputTimezone extends Component {
|
|||
/>
|
||||
<div className="settings-warning">
|
||||
<small>
|
||||
Time zone setting affects all time & date fields throughout
|
||||
application.
|
||||
<FormattedMessage id="settings_page.time_zone_warning" />
|
||||
</small>
|
||||
</div>
|
||||
<Button bsStyle="primary" onClick={this.props.disableEdit}>
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import React, { Component } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import styled from "styled-components";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
|
||||
import NotificationsSwitchGroup from "./NotificationsSwitchGroup";
|
||||
import { WHITE_COLOR } from "../../../../../app/constants/colors";
|
||||
|
@ -66,11 +67,11 @@ class NotificationsGroup extends Component {
|
|||
<div className="col-sm-10">
|
||||
<h5>
|
||||
<strong>
|
||||
{this.props.title}
|
||||
<FormattedMessage id={this.props.title} />
|
||||
</strong>
|
||||
</h5>
|
||||
<p>
|
||||
{this.props.subtitle}
|
||||
<FormattedMessage id={this.props.subtitle} />
|
||||
</p>
|
||||
<NotificationsSwitchGroup type={this.props.type} />
|
||||
</div>
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import React, { Component } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import styled from "styled-components";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
|
||||
import {
|
||||
WHITE_COLOR,
|
||||
|
@ -47,14 +48,14 @@ class NotificationsSwitch extends Component {
|
|||
disabled={this.props.isDisabled}
|
||||
onClick={this.handleClick}
|
||||
>
|
||||
No
|
||||
<FormattedMessage id="settings_page.no" />
|
||||
</LeftButton>
|
||||
<RightButton
|
||||
className="btn btn-primary"
|
||||
disabled={this.props.isDisabled}
|
||||
onClick={this.handleClick}
|
||||
>
|
||||
Yes
|
||||
<FormattedMessage id="settings_page.yes" />
|
||||
</RightButton>
|
||||
</div>
|
||||
);
|
||||
|
@ -66,14 +67,14 @@ class NotificationsSwitch extends Component {
|
|||
disabled={this.props.isDisabled}
|
||||
onClick={this.handleClick}
|
||||
>
|
||||
No
|
||||
<FormattedMessage id="settings_page.no" />
|
||||
</LeftButton>
|
||||
<RightButton
|
||||
className="btn btn-default"
|
||||
disabled={this.props.isDisabled}
|
||||
onClick={this.handleClick}
|
||||
>
|
||||
Yes
|
||||
<FormattedMessage id="settings_page.yes" />
|
||||
</RightButton>
|
||||
</div>
|
||||
);
|
||||
|
@ -82,7 +83,7 @@ class NotificationsSwitch extends Component {
|
|||
return (
|
||||
<Wrapper className="row">
|
||||
<div className="col-sm-4 col-sm-offset-1">
|
||||
{this.props.title}
|
||||
<FormattedMessage id={this.props.title} />
|
||||
</div>
|
||||
<div className="col-sm-7">
|
||||
{switchBtn}
|
||||
|
|
|
@ -103,13 +103,13 @@ class NotificationsSwitchGroup extends Component {
|
|||
return (
|
||||
<div>
|
||||
<NotificationsSwitch
|
||||
title="Show in sciNote"
|
||||
title="settings_page.show_in_scinote"
|
||||
isSwitchOn={this.state.isSciNoteSwitchOn}
|
||||
toggleSwitch={this.toggleFirstSwitch}
|
||||
isDisabled={this.isSwitchDisabled()}
|
||||
/>
|
||||
<NotificationsSwitch
|
||||
title="Notify me via email"
|
||||
title="settings_page.notify_me_via_email"
|
||||
isSwitchOn={this.state.isEmailSwitchOn}
|
||||
toggleSwitch={this.toggleSecondSwitch}
|
||||
isDisabled={!this.state.isSciNoteSwitchOn}
|
||||
|
|
|
@ -2,6 +2,7 @@ import React, { Component } from "react";
|
|||
import { connect } from "react-redux";
|
||||
import PropTypes from "prop-types";
|
||||
import styled from "styled-components";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
|
||||
import InputDisabled from "../InputDisabled";
|
||||
import InputTimezone from "./InputTimezone";
|
||||
|
@ -61,15 +62,14 @@ class SettingsPreferences extends Component {
|
|||
timezoneField = (
|
||||
<WrapperInputDisabled>
|
||||
<InputDisabled
|
||||
labelValue="Time zone"
|
||||
labelTitle="settings_page.time_zone"
|
||||
inputValue={this.props.timezone}
|
||||
inputType="text"
|
||||
enableEdit={() => this.toggleIsEditable(isTimeZoneEditable)}
|
||||
/>
|
||||
<div className="settings-warning">
|
||||
<small>
|
||||
Time zone setting affects all time & date fields throughout
|
||||
application.
|
||||
<FormattedMessage id="settings_page.time_zone_warning" />
|
||||
</small>
|
||||
</div>
|
||||
</WrapperInputDisabled>
|
||||
|
@ -83,24 +83,24 @@ class SettingsPreferences extends Component {
|
|||
<h3>Notifications</h3>
|
||||
<NotificationsGroup
|
||||
type={ASSIGNMENT_NOTIFICATION}
|
||||
title="Assignement"
|
||||
subtitle="Assignment notifications appear whenever you get assigned to a team, project, task."
|
||||
title="settings_page.assignement"
|
||||
subtitle="settings_page.assignement_msg"
|
||||
imgUrl=""
|
||||
iconClasses="fa fa-newspaper-o"
|
||||
iconBackground={MAIN_COLOR_BLUE}
|
||||
/>
|
||||
<NotificationsGroup
|
||||
type={RECENT_NOTIFICATION}
|
||||
title="Recent changes"
|
||||
subtitle="Recent changes notifications appear whenever there is a change on a task you are assigned to."
|
||||
title="settings_page.recent_changes"
|
||||
subtitle="settings_page.recent_changes_msg"
|
||||
imgUrl={this.props.avatarPath}
|
||||
iconClasses=""
|
||||
iconBackground=""
|
||||
/>
|
||||
<NotificationsGroup
|
||||
type={SYSTEM_NOTIFICATION}
|
||||
title="System message"
|
||||
subtitle="System message notifications are specifically sent by site maintainers to notify all users about a system update."
|
||||
title="settings_page.system_message"
|
||||
subtitle="settings_page.system_message_msg"
|
||||
imgUrl=""
|
||||
iconClasses="glyphicon glyphicon-tower"
|
||||
iconBackground={ICON_GREEN_COLOR}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import React from "react";
|
||||
import PropTypes, { string } from "prop-types";
|
||||
import styled from "styled-components";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
|
||||
import {
|
||||
WHITE_COLOR,
|
||||
|
@ -28,7 +29,8 @@ const Avatar = props =>
|
|||
<AvatarWrapper onClick={props.enableEdit}>
|
||||
<img src={props.imgSource} alt="default avatar" />
|
||||
<EditAvatar className="text-center">
|
||||
<span className="glyphicon glyphicon-pencil" /> Edit Avatar
|
||||
<span className="glyphicon glyphicon-pencil" />
|
||||
<FormattedMessage id="settings_page.edit_avatar" />
|
||||
</EditAvatar>
|
||||
</AvatarWrapper>;
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ import React, { Component } from "react";
|
|||
import { connect } from "react-redux";
|
||||
import PropTypes from "prop-types";
|
||||
import styled from "styled-components";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
|
||||
import Avatar from "./Avatar";
|
||||
import InputDisabled from "../InputDisabled";
|
||||
|
@ -56,6 +57,7 @@ class MyProfile extends Component {
|
|||
if (this.state.isAvatarEditable) {
|
||||
avatarField = (
|
||||
<InputEnabled
|
||||
labelTitle="settings_page.avatar"
|
||||
labelValue="Avatar"
|
||||
inputType="file"
|
||||
inputValue=""
|
||||
|
@ -75,6 +77,7 @@ class MyProfile extends Component {
|
|||
if (this.state.isPasswordEditable) {
|
||||
passwordField = (
|
||||
<InputEnabled
|
||||
labelTitle="settings_page.change_password"
|
||||
labelValue="Change password"
|
||||
inputType="password"
|
||||
inputValue=""
|
||||
|
@ -85,7 +88,7 @@ class MyProfile extends Component {
|
|||
} else {
|
||||
passwordField = (
|
||||
<InputDisabled
|
||||
labelValue="Change password"
|
||||
labelTitle="settings_page.change_password"
|
||||
inputType="password"
|
||||
inputValue=""
|
||||
enableEdit={() => this.toggleIsEditable(isPasswordEditable)}
|
||||
|
@ -96,6 +99,7 @@ class MyProfile extends Component {
|
|||
if (this.state.isEmailEditable) {
|
||||
emailField = (
|
||||
<InputEnabled
|
||||
labelTitle="settings_page.new_email"
|
||||
labelValue="New email"
|
||||
inputType="email"
|
||||
inputValue={this.props.email}
|
||||
|
@ -106,7 +110,7 @@ class MyProfile extends Component {
|
|||
} else {
|
||||
emailField = (
|
||||
<InputDisabled
|
||||
labelValue="New email"
|
||||
labelTitle="settings_page.new_email"
|
||||
inputValue={this.props.email}
|
||||
inputType="email"
|
||||
enableEdit={() => this.toggleIsEditable(isEmailEditable)}
|
||||
|
@ -117,6 +121,7 @@ class MyProfile extends Component {
|
|||
if (this.state.areInitialsEditable) {
|
||||
initialsField = (
|
||||
<InputEnabled
|
||||
labelTitle="settings_page.initials"
|
||||
labelValue="Initials"
|
||||
inputType="text"
|
||||
inputValue={this.props.initials}
|
||||
|
@ -127,7 +132,7 @@ class MyProfile extends Component {
|
|||
} else {
|
||||
initialsField = (
|
||||
<InputDisabled
|
||||
labelValue="Initials"
|
||||
labelTitle="settings_page.initials"
|
||||
inputValue={this.props.initials}
|
||||
inputType="text"
|
||||
enableEdit={() => this.toggleIsEditable(areInitialsEditable)}
|
||||
|
@ -138,6 +143,7 @@ class MyProfile extends Component {
|
|||
if (this.state.isFullNameEditable) {
|
||||
fullNameField = (
|
||||
<InputEnabled
|
||||
labelTitle="settings_page.full_name"
|
||||
labelValue="Full name"
|
||||
inputType="text"
|
||||
inputValue={this.props.fullName}
|
||||
|
@ -148,7 +154,7 @@ class MyProfile extends Component {
|
|||
} else {
|
||||
fullNameField = (
|
||||
<InputDisabled
|
||||
labelValue="Full name"
|
||||
labelTitle="settings_page.full_name"
|
||||
inputValue={this.props.fullName}
|
||||
inputType="text"
|
||||
enableEdit={() => this.toggleIsEditable(isFullNameEditable)}
|
||||
|
@ -158,8 +164,12 @@ class MyProfile extends Component {
|
|||
|
||||
return (
|
||||
<div>
|
||||
<h2>My Profile</h2>
|
||||
<AvatarLabel>Avatar</AvatarLabel>
|
||||
<h2>
|
||||
<FormattedMessage id="settings_page.my_profile" />
|
||||
</h2>
|
||||
<AvatarLabel>
|
||||
<FormattedMessage id="settings_page.avatar" />
|
||||
</AvatarLabel>
|
||||
{avatarField}
|
||||
{fullNameField}
|
||||
{initialsField}
|
||||
|
|
|
@ -2,6 +2,7 @@ import React, { Component } from "react";
|
|||
import { connect } from "react-redux";
|
||||
import PropTypes from "prop-types";
|
||||
import styled from "styled-components";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
|
||||
import MyStatisticsBox from "./MyStatisticsBox";
|
||||
|
||||
|
@ -15,25 +16,33 @@ class MyStatistics extends Component {
|
|||
const stats = this.props.statistics;
|
||||
|
||||
const statBoxes = () => {
|
||||
let boxes = <div>Loading...</div>;
|
||||
let boxes = (
|
||||
<div>
|
||||
<FormattedMessage id="general.loading" />
|
||||
</div>
|
||||
);
|
||||
if (stats) {
|
||||
boxes = (
|
||||
<Wrapper>
|
||||
<MyStatisticsBox
|
||||
typeLength={stats.number_of_teams}
|
||||
typeText="Teams"
|
||||
plural="settings_page.teams"
|
||||
singular="settings_page.team"
|
||||
/>
|
||||
<MyStatisticsBox
|
||||
typeLength={stats.number_of_projects}
|
||||
typeText="Projects"
|
||||
plural="settings_page.projects"
|
||||
singular="settings_page.project"
|
||||
/>
|
||||
<MyStatisticsBox
|
||||
typeLength={stats.number_of_experiments}
|
||||
typeText="Experiments"
|
||||
plural="settings_page.experiments"
|
||||
singular="settings_page.experiment"
|
||||
/>
|
||||
<MyStatisticsBox
|
||||
typeLength={stats.number_of_protocols}
|
||||
typeText="Protocols"
|
||||
plural="settings_page.protocols"
|
||||
singular="settings_page.protocol"
|
||||
/>
|
||||
</Wrapper>
|
||||
);
|
||||
|
@ -44,7 +53,9 @@ class MyStatistics extends Component {
|
|||
|
||||
return (
|
||||
<div>
|
||||
<h2>My Statistics</h2>
|
||||
<h2>
|
||||
<FormattedMessage id="settings_page.my_statistics" />
|
||||
</h2>
|
||||
|
||||
{statBoxes()}
|
||||
</div>
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import React from "react";
|
||||
import styled from "styled-components";
|
||||
import PropTypes from "prop-types";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
|
||||
import { MAIN_COLOR_BLUE } from "../../../../../app/constants/colors";
|
||||
|
||||
|
@ -21,13 +22,16 @@ const MyStatisticsBox = props =>
|
|||
{props.typeLength}
|
||||
</h2>
|
||||
<h5>
|
||||
{props.typeText}
|
||||
{props.typeLength === 1
|
||||
? <FormattedMessage id={props.singular} />
|
||||
: <FormattedMessage id={props.plural} />}
|
||||
</h5>
|
||||
</Box>;
|
||||
|
||||
MyStatisticsBox.propTypes = {
|
||||
typeLength: PropTypes.number.isRequired,
|
||||
typeText: PropTypes.string.isRequired
|
||||
plural: PropTypes.string.isRequired,
|
||||
singular: PropTypes.string.isRequired
|
||||
};
|
||||
|
||||
export default MyStatisticsBox;
|
||||
|
|
Loading…
Add table
Reference in a new issue