diff --git a/app/javascript/src/components/PageTitle/index.jsx b/app/javascript/src/components/PageTitle/index.jsx new file mode 100644 index 000000000..5700ef88a --- /dev/null +++ b/app/javascript/src/components/PageTitle/index.jsx @@ -0,0 +1,27 @@ +// @flow +import React from "react"; +import type { Node } from "react"; +import type { MessageDescriptor } from "flow-typed"; +import DocumentTitle from "react-document-title"; +import { formatMessage, defineMessages, injectIntl } from "react-intl"; + +type Props = { + intl: any, + localeID: string, + values?: any, + children: Node +}; + +const PageTitle = (props: Props): Node => { + const message = defineMessages({ + placeholder: { id: props.localeID } + }); + const title = props.intl.formatMessage(message.placeholder, props.values); + return {props.children}; +}; + +PageTitle.defaultProps = { + values: {} +}; + +export default injectIntl(PageTitle); diff --git a/app/javascript/src/config/locales/messages.js b/app/javascript/src/config/locales/messages.js index 26328ca30..d3ff9b457 100644 --- a/app/javascript/src/config/locales/messages.js +++ b/app/javascript/src/config/locales/messages.js @@ -8,6 +8,14 @@ export default { loading: "Loading ...", upload: "Upload" }, + page_title: { + root: "SciNote", + settings_preference_page: "SciNote | Settings | Preferences", + settings_profile_page: "SciNote | Settings | Profile", + team_page: "SciNote | Settings | Teams | {name}", + all_teams_page: "SciNote | Settings | Teams", + new_team_page: "SciNote | Settings | Teams | New" + }, error_messages: { text_too_short: "is too short (minimum is {min_length} characters)", text_too_long: "is too long (maximum is {max_length} characters)", diff --git a/app/javascript/src/scenes/SettingsPage/index.jsx b/app/javascript/src/scenes/SettingsPage/index.jsx index bf35a5008..8125b54ad 100644 --- a/app/javascript/src/scenes/SettingsPage/index.jsx +++ b/app/javascript/src/scenes/SettingsPage/index.jsx @@ -16,6 +16,7 @@ import { import { SETTINGS_PATH, SETTINGS_TEAMS } from "../../config/api_endpoints"; +import PageTitle from "../../components/PageTitle"; import NotFound from "../../components/404/NotFound"; import SettingsProfile from "./scenes/profile"; import SettingsPreferences from "./scenes/preferences"; @@ -61,7 +62,7 @@ export default class SettingsPage extends Component<*, State> { render() { return ( -
+
-
+ ); } } diff --git a/app/javascript/src/scenes/SettingsPage/scenes/preferences/index.jsx b/app/javascript/src/scenes/SettingsPage/scenes/preferences/index.jsx index f0c7d9ad7..56a45458b 100644 --- a/app/javascript/src/scenes/SettingsPage/scenes/preferences/index.jsx +++ b/app/javascript/src/scenes/SettingsPage/scenes/preferences/index.jsx @@ -3,6 +3,7 @@ import React, { Component } from "react"; import { FormattedMessage } from "react-intl"; import { getUserPreferencesInfo } from "../../../../services/api/users_api"; +import PageTitle from "../../../../components/PageTitle"; import SettingsAccountWrapper from "../../components/SettingsAccountWrapper"; import InputTimezone from "./components/InputTimezone"; import NotificationsGroup from "./components/NotificationsGroup"; @@ -60,48 +61,46 @@ class SettingsPreferences extends Component { render() { return ( - -
- -

- -

- - - -
-
+ + +
+ +

+ +

+ + + +
+
+
); } } diff --git a/app/javascript/src/scenes/SettingsPage/scenes/profile/index.jsx b/app/javascript/src/scenes/SettingsPage/scenes/profile/index.jsx index ed852af62..f162b87a1 100644 --- a/app/javascript/src/scenes/SettingsPage/scenes/profile/index.jsx +++ b/app/javascript/src/scenes/SettingsPage/scenes/profile/index.jsx @@ -1,29 +1,33 @@ // @flow import React, { Component } from "react"; + +import PageTitle from "../../../../components/PageTitle"; import SettingsAccountWrapper from "../../components/SettingsAccountWrapper"; import MyProfile from "./components/MyProfile"; import MyStatistics from "./components/MyStatistics"; type Props = { tabState: Function -} +}; class SettingsProfile extends Component { componentDidMount() { - this.props.tabState("1") + this.props.tabState("1"); } - + render() { return ( - -
- -
-
- -
-
+ + +
+ +
+
+ +
+
+
); } } diff --git a/app/javascript/src/scenes/SettingsPage/scenes/team/index.jsx b/app/javascript/src/scenes/SettingsPage/scenes/team/index.jsx index 96186842a..258f7d1a9 100644 --- a/app/javascript/src/scenes/SettingsPage/scenes/team/index.jsx +++ b/app/javascript/src/scenes/SettingsPage/scenes/team/index.jsx @@ -15,6 +15,7 @@ import { getTeamDetails } from "../../../../services/api/teams_api"; import { SETTINGS_TEAMS_ROUTE } from "../../../../config/routes"; import { BORDER_LIGHT_COLOR } from "../../../../config/constants/colors"; +import PageTitle from "../../../../components/PageTitle"; import TeamsMembers from "./components/TeamsMembers"; import UpdateTeamDescriptionModal from "./components/UpdateTeamDescriptionModal"; import UpdateTeamNameModal from "./components/UpdateTeamNameModal"; @@ -108,7 +109,7 @@ class SettingsTeam extends Component { // set team tab on active (this: any).props.tabState("2"); const { id } = this.props.match.params; - if(id) { + if (id) { getTeamDetails(parseInt(id)).then(response => { const { team, users } = response; (this: any).setState({ users, team }); @@ -165,86 +166,91 @@ class SettingsTeam extends Component { render() { return ( - - - - - + + + + + + + + + + {this.state.team.name} - - - {this.state.team.name} - - - - - {this.state.team.name} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {this.renderDescription()} - - - - - - {this.renderEditNameModal()} - + + + + {this.state.team.name} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {this.renderDescription()} + + + + + + {this.renderEditNameModal()} + + ); } } diff --git a/app/javascript/src/scenes/SettingsPage/scenes/teams/index.jsx b/app/javascript/src/scenes/SettingsPage/scenes/teams/index.jsx index 27facb24c..699eb14be 100644 --- a/app/javascript/src/scenes/SettingsPage/scenes/teams/index.jsx +++ b/app/javascript/src/scenes/SettingsPage/scenes/teams/index.jsx @@ -6,10 +6,11 @@ import { Breadcrumb } from "react-bootstrap"; import { connect } from "react-redux"; import { FormattedMessage } from "react-intl"; import type { State } from "flow-typed"; -import type { MapStateToProps } from "react-redux" +import type { MapStateToProps } from "react-redux"; import { BORDER_LIGHT_COLOR } from "../../../../config/constants/colors"; +import PageTitle from "../../../../components/PageTitle"; import TeamsPageDetails from "./components/TeamsPageDetails"; import TeamsDataTable from "./components/TeamsDataTable"; @@ -25,12 +26,12 @@ const Wrapper = styled.div` type Props = { tabState: Function, teams: Array -} +}; class SettingsTeams extends Component { static defaultProps = { teams: [{ id: 0, name: "", current_team: "", role: "", members: 0 }] - } + }; componentDidMount() { // set team tab on active @@ -40,15 +41,17 @@ class SettingsTeams extends Component { render() { const { teams } = this.props; return ( - - - - - - - - - + + + + + + + + + + + ); } } diff --git a/app/javascript/src/scenes/SettingsPage/scenes/teams/new/index.jsx b/app/javascript/src/scenes/SettingsPage/scenes/teams/new/index.jsx index 16691c216..ad1962d2b 100644 --- a/app/javascript/src/scenes/SettingsPage/scenes/teams/new/index.jsx +++ b/app/javascript/src/scenes/SettingsPage/scenes/teams/new/index.jsx @@ -32,6 +32,7 @@ import { getTeamsList } from "../../../../../components/actions/TeamsActions"; import { BORDER_LIGHT_COLOR } from "../../../../../config/constants/colors"; +import PageTitle from "../../../../../components/PageTitle"; import NameFormControl from "./components/NameFormControl"; const Wrapper = styled.div` @@ -245,48 +246,50 @@ class SettingsNewTeam extends Component { !_.isEmpty(this.state.formErrors.description); return ( - - - - - - - - - - - - -
- - {this.renderTeamNameFormGroup()} - - - - - - - {this.renderTeamDescriptionFormGroup()} - - - - - - + + + - + + + - -
-
+ + + + + +
+ + {this.renderTeamNameFormGroup()} + + + + + + + {this.renderTeamDescriptionFormGroup()} + + + + + + + + + + +
+ + ); } } diff --git a/package.json b/package.json index c304568ee..5f815adba 100644 --- a/package.json +++ b/package.json @@ -72,6 +72,7 @@ "react-bootstrap-table": "^4.0.0", "react-bootstrap-timezone-picker": "^1.0.11", "react-data-grid": "^2.0.2", + "react-document-title": "^2.0.3", "react-dom": "15.6.1", "react-intl": "^2.3.0", "react-intl-redux": "^0.6.0", diff --git a/yarn.lock b/yarn.lock index 3cedba29a..a7d39944b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2289,6 +2289,10 @@ exenv@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/exenv/-/exenv-1.2.0.tgz#3835f127abf075bfe082d0aed4484057c78e3c89" +exenv@^1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/exenv/-/exenv-1.2.2.tgz#2ae78e85d9894158670b03d47bec1f03bd91bb9d" + expand-brackets@^0.1.4: version "0.1.5" resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" @@ -5018,6 +5022,13 @@ react-data-grid@^2.0.2: version "2.0.60" resolved "https://registry.yarnpkg.com/react-data-grid/-/react-data-grid-2.0.60.tgz#4a1549d4dad032677439f25dbcf1036ab966032f" +react-document-title@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/react-document-title/-/react-document-title-2.0.3.tgz#bbf922a0d71412fc948245e4283b2412df70f2b9" + dependencies: + prop-types "^15.5.6" + react-side-effect "^1.0.2" + react-dom-factories@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/react-dom-factories/-/react-dom-factories-1.0.1.tgz#c50692ac5ff1adb39d86dfe6dbe3485dacf58455" @@ -5124,6 +5135,13 @@ react-s-alert@^1.3.0: dependencies: babel-runtime "^6.23.0" +react-side-effect@^1.0.2: + version "1.1.3" + resolved "https://registry.yarnpkg.com/react-side-effect/-/react-side-effect-1.1.3.tgz#512c25abe0dec172834c4001ec5c51e04d41bc5c" + dependencies: + exenv "^1.2.1" + shallowequal "^1.0.1" + react-tagsinput@^3.17.0: version "3.18.0" resolved "https://registry.yarnpkg.com/react-tagsinput/-/react-tagsinput-3.18.0.tgz#40e036fc0f4c3d6b4689858189ab02926717a818" @@ -5601,6 +5619,10 @@ shallow-clone@^0.1.2: lazy-cache "^0.2.3" mixin-object "^2.0.1" +shallowequal@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/shallowequal/-/shallowequal-1.0.2.tgz#1561dbdefb8c01408100319085764da3fcf83f8f" + shebang-command@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"