diff --git a/scm-ui/ui-webapp/src/containers/App.tsx b/scm-ui/ui-webapp/src/containers/App.tsx index 2bb61f1a3c..52026a44dc 100644 --- a/scm-ui/ui-webapp/src/containers/App.tsx +++ b/scm-ui/ui-webapp/src/containers/App.tsx @@ -27,7 +27,15 @@ import { connect } from "react-redux"; import { compose } from "redux"; import { WithTranslation, withTranslation } from "react-i18next"; import { withRouter } from "react-router-dom"; -import { fetchMe, getFetchMeFailure, getMe, isAuthenticated, isFetchMePending } from "../modules/auth"; +import { + fetchMe, + getFetchMeFailure, + getMe, + isAuthenticated, + isFetchMePending, + isLoginPending, + isLogoutPending +} from "../modules/auth"; import { ErrorPage, Footer, Header, Loading, PrimaryNavigation } from "@scm-manager/ui-components"; import { Links, Me } from "@scm-manager/ui-types"; import { @@ -37,6 +45,7 @@ import { getMeLink, isFetchIndexResourcesPending } from "../modules/indexResource"; +import Login from "./Login"; type Props = WithTranslation & { me: Me; @@ -64,12 +73,14 @@ class App extends Component { let content; const navigation = authenticated ? : ""; - if (loading) { + if (!authenticated) { + content = ; + } else if (loading) { content = ; } else if (error) { content = ; - } else if (me) { - content =
; + } else { + content =
; } return (
@@ -88,9 +99,9 @@ const mapDispatchToProps = (dispatch: any) => { }; const mapStateToProps = (state: any) => { - const authenticated = isAuthenticated(state); + const authenticated = isAuthenticated(state) && !isLogoutPending(state); const me = getMe(state); - const loading = isFetchMePending(state) || isFetchIndexResourcesPending(state); + const loading = isFetchMePending(state) || isFetchIndexResourcesPending(state) || isLoginPending(state); const error = getFetchMeFailure(state) || getFetchIndexResourcesFailure(state); const links = getLinks(state); const meLink = getMeLink(state); diff --git a/scm-ui/ui-webapp/src/containers/Login.tsx b/scm-ui/ui-webapp/src/containers/Login.tsx index 26fef08bdb..f40eef5921 100644 --- a/scm-ui/ui-webapp/src/containers/Login.tsx +++ b/scm-ui/ui-webapp/src/containers/Login.tsx @@ -23,15 +23,17 @@ */ import React from "react"; import { connect } from "react-redux"; -import { Redirect, withRouter } from "react-router-dom"; +import { Redirect, RouteComponentProps, withRouter } from "react-router-dom"; import { compose } from "redux"; import styled from "styled-components"; -import { getLoginFailure, isAnonymous, isLoginPending, login } from "../modules/auth"; +import { getLoginFailure, getMe, isAnonymous, isLoginPending, login } from "../modules/auth"; import { getLoginInfoLink, getLoginLink } from "../modules/indexResource"; import LoginInfo from "../components/LoginInfo"; +import { Me } from "@scm-manager/ui-types"; -type Props = { +type Props = RouteComponentProps & { authenticated: boolean; + me: Me; loading: boolean; error?: Error; link: string; @@ -39,10 +41,6 @@ type Props = { // dispatcher props login: (link: string, username: string, password: string) => void; - - // context props - from: any; - location: any; }; const HeroSection = styled.section` @@ -65,9 +63,9 @@ class Login extends React.Component { }; render() { - const { authenticated, ...restProps } = this.props; + const { authenticated, me, ...restProps } = this.props; - if (authenticated) { + if (authenticated && !!me) { return this.renderRedirect(); } @@ -87,12 +85,14 @@ class Login extends React.Component { const mapStateToProps = (state: any) => { const authenticated = state?.auth?.me && !isAnonymous(state.auth.me); + const me = getMe(state); const loading = isLoginPending(state); const error = getLoginFailure(state); const link = getLoginLink(state); const loginInfoLink = getLoginInfoLink(state); return { authenticated, + me, loading, error, link, diff --git a/scm-ui/ui-webapp/src/containers/Logout.tsx b/scm-ui/ui-webapp/src/containers/Logout.tsx index 1021c987f2..dcf0578dd1 100644 --- a/scm-ui/ui-webapp/src/containers/Logout.tsx +++ b/scm-ui/ui-webapp/src/containers/Logout.tsx @@ -24,52 +24,48 @@ import React from "react"; import { connect } from "react-redux"; import { WithTranslation, withTranslation } from "react-i18next"; -import { Redirect } from "react-router-dom"; -import { getLogoutFailure, isLogoutPending, isRedirecting, logout } from "../modules/auth"; +import { getLogoutFailure, logout } from "../modules/auth"; import { ErrorPage, Loading } from "@scm-manager/ui-components"; -import { getLoginLink, getLogoutLink } from "../modules/indexResource"; +import { getLogoutLink } from "../modules/indexResource"; +import { RouteComponentProps, withRouter } from "react-router-dom"; +import { compose } from "redux"; -type Props = WithTranslation & { - authenticated: boolean; - loading: boolean; - redirecting: boolean; - error: Error; - logoutLink: string; +type Props = RouteComponentProps & + WithTranslation & { + error: Error; + logoutLink: string; - // dispatcher functions - logout: (link: string) => void; -}; + // dispatcher functions + logout: (link: string) => void; + }; class Logout extends React.Component { componentDidMount() { - if (this.props.logoutLink) { - this.props.logout(this.props.logoutLink); - } + new Promise((resolve, reject) => { + setTimeout(() => { + if (this.props.logoutLink) { + this.props.logout(this.props.logoutLink); + resolve(this.props.history.push("/login")); + } + }); + }); } render() { - const { authenticated, redirecting, loading, error, t } = this.props; + const { error, t } = this.props; if (error) { return ; - } else if (loading || authenticated || redirecting) { - return ; } else { - return ; + return ; } } } const mapStateToProps = (state: any) => { - const authenticated = state.auth.me && !getLoginLink(state); - const loading = isLogoutPending(state); - const redirecting = isRedirecting(state); const error = getLogoutFailure(state); const logoutLink = getLogoutLink(state); return { - authenticated, - loading, - redirecting, error, logoutLink }; @@ -81,4 +77,4 @@ const mapDispatchToProps = (dispatch: any) => { }; }; -export default connect(mapStateToProps, mapDispatchToProps)(withTranslation("commons")(Logout)); +export default compose(withTranslation("commons"), withRouter, connect(mapStateToProps, mapDispatchToProps))(Logout); diff --git a/scm-ui/ui-webapp/src/containers/Main.tsx b/scm-ui/ui-webapp/src/containers/Main.tsx index cf582f20bf..03cb3262b1 100644 --- a/scm-ui/ui-webapp/src/containers/Main.tsx +++ b/scm-ui/ui-webapp/src/containers/Main.tsx @@ -24,7 +24,7 @@ import React from "react"; import { Redirect, Route, Switch, withRouter } from "react-router-dom"; -import { Links } from "@scm-manager/ui-types"; +import { Links, Me } from "@scm-manager/ui-types"; import Overview from "../repos/containers/Overview"; import Users from "../users/containers/Users"; @@ -48,15 +48,22 @@ import Admin from "../admin/containers/Admin"; import Profile from "./Profile"; type Props = { + me: Me; authenticated?: boolean; links: Links; }; class Main extends React.Component { render() { - const { authenticated, links } = this.props; + const { authenticated, me, links } = this.props; const redirectUrlFactory = binder.getExtension("main.redirect", this.props); - let url = "/repos/"; + let url = "/"; + if (authenticated) { + url = "/repos/"; + } + if (!me) { + url = "/login"; + } if (redirectUrlFactory) { url = redirectUrlFactory(this.props); } diff --git a/scm-ui/ui-webapp/src/repos/containers/Overview.tsx b/scm-ui/ui-webapp/src/repos/containers/Overview.tsx index 5b01e7e225..66719b3fca 100644 --- a/scm-ui/ui-webapp/src/repos/containers/Overview.tsx +++ b/scm-ui/ui-webapp/src/repos/containers/Overview.tsx @@ -25,8 +25,7 @@ import React from "react"; import { connect } from "react-redux"; import { RouteComponentProps, withRouter } from "react-router-dom"; import { WithTranslation, withTranslation } from "react-i18next"; -import { History } from "history"; -import { RepositoryCollection } from "@scm-manager/ui-types"; +import { Me, RepositoryCollection } from "@scm-manager/ui-types"; import { CreateButton, LinkPaginator, @@ -45,9 +44,11 @@ import { isFetchReposPending } from "../modules/repos"; import RepositoryList from "../components/list"; +import { fetchMe, isFetchMePending } from "../../modules/auth"; type Props = WithTranslation & RouteComponentProps & { + me: Me; loading: boolean; error: Error; showCreateButton: boolean; @@ -61,13 +62,15 @@ type Props = WithTranslation & class Overview extends React.Component { componentDidMount() { - const { fetchReposByPage, reposLink, page, location } = this.props; - fetchReposByPage(reposLink, page, urls.getQueryStringFromLocation(location)); + const { me, fetchReposByPage, reposLink, page, location } = this.props; + if (me) { + fetchReposByPage(reposLink, page, urls.getQueryStringFromLocation(location)); + } } componentDidUpdate = (prevProps: Props) => { - const { loading, collection, page, reposLink, location, fetchReposByPage } = this.props; - if (collection && page && !loading) { + const { me, loading, collection, page, reposLink, location, fetchReposByPage } = this.props; + if (collection && page && !loading && me) { const statePage: number = collection.page + 1; if (page !== statePage || prevProps.location.search !== location.search) { fetchReposByPage(reposLink, page, urls.getQueryStringFromLocation(location)); @@ -125,13 +128,15 @@ class Overview extends React.Component { const mapStateToProps = (state: any, ownProps: Props) => { const { match } = ownProps; + const me = fetchMe(state); const collection = getRepositoryCollection(state); - const loading = isFetchReposPending(state); + const loading = isFetchReposPending(state) || isFetchMePending(state); const error = getFetchReposFailure(state); const page = urls.getPageFromMatch(match); const showCreateButton = isAbleToCreateRepos(state); const reposLink = getRepositoriesLink(state); return { + me, collection, loading, error,