diff --git a/scm-ui-components/packages/ui-components/src/layout/Footer.js b/scm-ui-components/packages/ui-components/src/layout/Footer.js index 4072711c7a..11ed52ac63 100644 --- a/scm-ui-components/packages/ui-components/src/layout/Footer.js +++ b/scm-ui-components/packages/ui-components/src/layout/Footer.js @@ -1,6 +1,7 @@ //@flow import React from "react"; import type { Me } from "@scm-manager/ui-types"; +import {Link} from "react-router-dom"; type Props = { me?: Me @@ -15,7 +16,7 @@ class Footer extends React.Component { return ( ); diff --git a/scm-ui-components/packages/ui-types/src/Me.js b/scm-ui-components/packages/ui-types/src/Me.js index 65e4fc8336..ab67debae7 100644 --- a/scm-ui-components/packages/ui-types/src/Me.js +++ b/scm-ui-components/packages/ui-types/src/Me.js @@ -2,5 +2,6 @@ export type Me = { name: string, - displayName: string + displayName: string, + mail: string }; diff --git a/scm-ui/public/locales/en/commons.json b/scm-ui/public/locales/en/commons.json index b1bad56993..05e9f79d16 100644 --- a/scm-ui/public/locales/en/commons.json +++ b/scm-ui/public/locales/en/commons.json @@ -38,5 +38,14 @@ "paginator": { "next": "Next", "previous": "Previous" + }, + "profile": { + "actions-label": "Actions", + "username": "Username", + "displayName": "Display Name", + "mail": "E-Mail", + "change-password": "Change password", + "error-title": "Error", + "error-subtitle": "Cannot display profile" } } diff --git a/scm-ui/src/users/components/ChangeUserPassword.js b/scm-ui/src/containers/ChangeUserPassword.js similarity index 90% rename from scm-ui/src/users/components/ChangeUserPassword.js rename to scm-ui/src/containers/ChangeUserPassword.js index e22d806fb4..ccf0a81194 100644 --- a/scm-ui/src/users/components/ChangeUserPassword.js +++ b/scm-ui/src/containers/ChangeUserPassword.js @@ -1,15 +1,15 @@ // @flow import React from "react"; -import type { User } from "@scm-manager/ui-types"; +import type { User } from "../../../scm-ui-components/packages/ui-types/src/index"; import { SubmitButton, Notification, ErrorNotification, InputField -} from "@scm-manager/ui-components"; +} from "../../../scm-ui-components/packages/ui-components/src/index"; import { translate } from "react-i18next"; -import { setPassword, updatePassword } from "./changePassword"; -import PasswordConfirmation from "./PasswordConfirmation"; +import { setPassword, updatePassword } from "../users/components/changePassword"; +import PasswordConfirmation from "../users/components/PasswordConfirmation"; type Props = { user: User, diff --git a/scm-ui/src/containers/Main.js b/scm-ui/src/containers/Main.js index 538d03ca48..f7dd07940f 100644 --- a/scm-ui/src/containers/Main.js +++ b/scm-ui/src/containers/Main.js @@ -19,7 +19,8 @@ import SingleGroup from "../groups/containers/SingleGroup"; import AddGroup from "../groups/containers/AddGroup"; import Config from "../config/containers/Config"; -import ChangeUserPassword from "../users/components/ChangeUserPassword"; +import ChangeUserPassword from "./ChangeUserPassword"; +import Profile from "./Profile"; type Props = { authenticated?: boolean @@ -79,11 +80,7 @@ class Main extends React.Component { path="/user/:name" component={SingleUser} /> - + { component={Config} authenticated={authenticated} /> + ); diff --git a/scm-ui/src/containers/Profile.js b/scm-ui/src/containers/Profile.js new file mode 100644 index 0000000000..5d9902f309 --- /dev/null +++ b/scm-ui/src/containers/Profile.js @@ -0,0 +1,62 @@ +// @flow + +import React from "react"; + +import { + Page, + Navigation, + Section, + MailLink +} from "../../../scm-ui-components/packages/ui-components/src/index"; +import { NavLink, Route } from "react-router-dom"; +import { getMe } from "../modules/auth"; +import { compose } from "redux"; +import { connect } from "react-redux"; +import { translate } from "react-i18next"; +import type { Me } from "../../../scm-ui-components/packages/ui-types/src/index"; +import AvatarWrapper from "../repos/components/changesets/AvatarWrapper"; +import { ErrorPage } from "@scm-manager/ui-components"; +import ChangeUserPassword from "./ChangeUserPassword"; +import ProfileInfo from "./ProfileInfo"; + +type Props = { + me: Me, + + // Context props + t: string => string +}; +type State = {}; + +class Profile extends React.Component { + render() { + const { me, t } = this.props; + + if (!me) { + return ( + + ); + } + + return ( + + } /> + + + ); + } +} + +const mapStateToProps = state => { + return { + me: getMe(state) + }; +}; + +export default compose( + translate("commons"), + connect(mapStateToProps) +)(Profile); diff --git a/scm-ui/src/containers/ProfileInfo.js b/scm-ui/src/containers/ProfileInfo.js new file mode 100644 index 0000000000..bd93495ddd --- /dev/null +++ b/scm-ui/src/containers/ProfileInfo.js @@ -0,0 +1,65 @@ +// @flow +import React from "react"; +import AvatarWrapper from "../repos/components/changesets/AvatarWrapper"; +import { NavLink } from "react-router-dom"; +import type { Me } from "@scm-manager/ui-types"; +import { MailLink, Navigation, Section } from "@scm-manager/ui-components"; +import { compose } from "redux"; +import { translate } from "react-i18next"; + +type Props = { + me: Me, + + // Context props + t: string => string +}; +type State = {}; + +class ProfileInfo extends React.Component { + render() { + const { me, t } = this.props; + return ( +
+ +
+
+

+ { + // TODO: add avatar + } +

+
+
+
+
+ + + + + + + + + + + + + + + +
{t("profile.username")}{me.name}
{t("profile.displayName")}{me.displayName}
{t("profile.mail")} + +
+
+
+ +
+ {t("profile.change-password")} + +
+
+ ); + } +} + +export default compose(translate("commons"))(ProfileInfo); diff --git a/scm-ui/src/modules/auth.js b/scm-ui/src/modules/auth.js index fe636ac9d3..691ae2b128 100644 --- a/scm-ui/src/modules/auth.js +++ b/scm-ui/src/modules/auth.js @@ -1,5 +1,5 @@ // @flow -import type { Me } from "@scm-manager/ui-components"; +import type { Me } from "@scm-manager/ui-types"; import * as types from "./types"; import { apiClient, UNAUTHORIZED_ERROR } from "@scm-manager/ui-components"; @@ -136,7 +136,11 @@ const callFetchMe = (link: string): Promise => { return response.json(); }) .then(json => { - return { name: json.name, displayName: json.displayName }; + return { + name: json.name, + displayName: json.displayName, + mail: json.mail + }; }); }; diff --git a/scm-ui/src/modules/auth.test.js b/scm-ui/src/modules/auth.test.js index 1839701e0a..7236f803a8 100644 --- a/scm-ui/src/modules/auth.test.js +++ b/scm-ui/src/modules/auth.test.js @@ -37,7 +37,11 @@ import { FETCH_INDEXRESOURCES_SUCCESS } from "./indexResource"; -const me = { name: "tricia", displayName: "Tricia McMillian" }; +const me = { + name: "tricia", + displayName: "Tricia McMillian", + mail: "trillian@heartofgold.universe" +}; describe("auth reducer", () => { it("should set me and login on successful fetch of me", () => {