Add sign-in prompt on Contributions page (#148)
This commit is contained in:
Родитель
43ba412443
Коммит
a8df22afe5
|
@ -7,9 +7,7 @@ import "./App.css";
|
|||
import Main from "./components/Main/Main";
|
||||
import Header from "./components/Header/Header";
|
||||
import DetailView from "./components/DetailView/DetailView";
|
||||
import LoginDialog from "./components/LoginDialog/LoginDialog";
|
||||
import Contribute from "./components/Contribute/Contribute";
|
||||
import PrivateRoute from "./components/PrivateRoute/PrivateRoute";
|
||||
import ContributionsPage from "./components/Contribute/Contribute";
|
||||
import { sampleActions } from "./actions/sampleActions";
|
||||
import { userActions } from "./actions/userActions";
|
||||
import { libraryService, userService } from "./services";
|
||||
|
@ -21,10 +19,11 @@ class App extends Component {
|
|||
.then(samples => this.props.getSamplesSuccess(samples))
|
||||
.catch(error => console.log(error));
|
||||
|
||||
this.props.getCurrentUserRequest();
|
||||
userService
|
||||
.getCurrentUser()
|
||||
.then(user => this.props.getCurrentUserSuccess(user))
|
||||
.catch(error => console.log(error));
|
||||
.catch(error => this.props.getCurrentUserFailure());
|
||||
}
|
||||
|
||||
render() {
|
||||
|
@ -37,8 +36,7 @@ class App extends Component {
|
|||
<Switch>
|
||||
<Route exact path="/" component={Main} />
|
||||
<Route path="/sample/:id" component={DetailView} />
|
||||
<Route exact path="/login" component={LoginDialog} />
|
||||
<PrivateRoute exact path="/contribute" component={Contribute} />
|
||||
<Route exact path="/contribute" component={ContributionsPage} />
|
||||
</Switch>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -52,7 +50,9 @@ function mapStateToProps(state) {
|
|||
|
||||
const mapDispatchToProps = {
|
||||
getSamplesSuccess: sampleActions.getSamplesSuccess,
|
||||
getCurrentUserSuccess: userActions.getCurrentUserSuccess
|
||||
getCurrentUserRequest: userActions.getCurrentUserRequest,
|
||||
getCurrentUserSuccess: userActions.getCurrentUserSuccess,
|
||||
getCurrentUserFailure: userActions.getCurrentUserFailure
|
||||
};
|
||||
const AppContainer = withRouter(
|
||||
connect(
|
||||
|
|
|
@ -4,6 +4,8 @@ export const sampleActionTypes = {
|
|||
};
|
||||
|
||||
export const userActionTypes = {
|
||||
GETCURRENTUSER_REQUEST: "GETCURRENTUSER_REQUEST",
|
||||
GETCURRENTUSER_SUCCESS: "GETCURRENTUSER_SUCCESS",
|
||||
GETCURRENTUSER_FAILURE: "GETCURRENTUSER_FAILURE",
|
||||
LOGOUT: "LOGOUT"
|
||||
};
|
||||
|
|
|
@ -1,10 +1,19 @@
|
|||
import { userActionTypes } from "./actionTypes";
|
||||
|
||||
export const userActions = {
|
||||
getCurrentUserRequest,
|
||||
getCurrentUserSuccess,
|
||||
getCurrentUserFailure,
|
||||
logout
|
||||
};
|
||||
|
||||
function getCurrentUserRequest(user) {
|
||||
return {
|
||||
type: userActionTypes.GETCURRENTUSER_REQUEST,
|
||||
user
|
||||
};
|
||||
}
|
||||
|
||||
function getCurrentUserSuccess(user) {
|
||||
return {
|
||||
type: userActionTypes.GETCURRENTUSER_SUCCESS,
|
||||
|
@ -12,6 +21,13 @@ function getCurrentUserSuccess(user) {
|
|||
};
|
||||
}
|
||||
|
||||
function getCurrentUserFailure(user) {
|
||||
return {
|
||||
type: userActionTypes.GETCURRENTUSER_FAILURE,
|
||||
user
|
||||
};
|
||||
}
|
||||
|
||||
function logout() {
|
||||
return {
|
||||
type: userActionTypes.LOGOUT
|
||||
|
|
|
@ -12,7 +12,6 @@ import { libraryService } from "../../services";
|
|||
import { sampleActions } from "../../actions/sampleActions";
|
||||
import * as formStyles from "./AddContributionForm.styles";
|
||||
import * as commonStyles from "../shared/Button.styles";
|
||||
import "./Contribute.scss";
|
||||
|
||||
const initialState = {
|
||||
showForm: false,
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
import React, { Component } from "react";
|
||||
import AddContributionForm from "./AddContributionForm";
|
||||
import ContributionsList from "./ContributionsList";
|
||||
import SignInDialog from "./SignInDialog";
|
||||
import PageHeaderWithBackButton from "../shared/PageHeaderWithBackButton";
|
||||
|
||||
import "./Contribute.scss";
|
||||
|
||||
class Contribute extends Component {
|
||||
class ContributionsPage extends Component {
|
||||
render() {
|
||||
return (
|
||||
<div className="contribute-page-container">
|
||||
|
@ -18,9 +19,10 @@ class Contribute extends Component {
|
|||
</PageHeaderWithBackButton>
|
||||
<AddContributionForm />
|
||||
<ContributionsList />
|
||||
<SignInDialog />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Contribute;
|
||||
export default ContributionsPage;
|
||||
|
|
|
@ -5,8 +5,12 @@ import ItemList from "../../components/ItemList/ItemList";
|
|||
|
||||
class ContributionsList extends Component {
|
||||
filteredSamples() {
|
||||
let { samples, user } = this.props;
|
||||
let { userName } = user || "__nouser__";
|
||||
let { loggedIn, user, samples } = this.props;
|
||||
let { userName } = user;
|
||||
if (!loggedIn || !userName) {
|
||||
return {};
|
||||
}
|
||||
|
||||
let filter = new RegExp(userName, "i");
|
||||
samples = samples.filter(
|
||||
el =>
|
||||
|
@ -41,6 +45,7 @@ class ContributionsList extends Component {
|
|||
function mapStateToProps(state) {
|
||||
return {
|
||||
samples: state.samples,
|
||||
loggedIn: state.authentication.loggedIn,
|
||||
user: state.authentication.user
|
||||
};
|
||||
}
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
import React, { Component } from "react";
|
||||
import { withRouter } from "react-router-dom";
|
||||
import { connect } from "react-redux";
|
||||
import { Dialog, DialogFooter, DefaultButton } from "office-ui-fabric-react";
|
||||
|
||||
import SignInButton from "../shared/SignInButton";
|
||||
|
||||
class SignInDialog extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.handleHomeButtonClick = this.handleHomeButtonClick.bind(this);
|
||||
}
|
||||
|
||||
handleHomeButtonClick() {
|
||||
this.props.history.push("/");
|
||||
}
|
||||
|
||||
render() {
|
||||
const footerStyles = {
|
||||
actionsRight: {
|
||||
textAlign: "center",
|
||||
marginRight: "0px"
|
||||
}
|
||||
};
|
||||
const buttonStyles = {
|
||||
root: {
|
||||
fontSize: "12px",
|
||||
height: "32px",
|
||||
minWidth: "40px"
|
||||
},
|
||||
label: {
|
||||
fontWeight: "normal"
|
||||
}
|
||||
};
|
||||
|
||||
const { loading, loggedIn } = this.props;
|
||||
if (loading) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Dialog
|
||||
hidden={loggedIn}
|
||||
dialogContentProps={{
|
||||
title: "Please sign in",
|
||||
subText: "Please sign in to continue."
|
||||
}}
|
||||
modalProps={{
|
||||
isBlocking: true
|
||||
}}
|
||||
>
|
||||
<DialogFooter styles={footerStyles}>
|
||||
<SignInButton />
|
||||
<DefaultButton
|
||||
styles={buttonStyles}
|
||||
text="Home"
|
||||
onClick={this.handleHomeButtonClick}
|
||||
/>
|
||||
</DialogFooter>
|
||||
</Dialog>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
loading: state.authentication.loading,
|
||||
loggedIn: state.authentication.loggedIn
|
||||
});
|
||||
|
||||
const SignInDialogContainer = connect(mapStateToProps)(SignInDialog);
|
||||
|
||||
export default withRouter(SignInDialogContainer);
|
|
@ -5,7 +5,7 @@ import { ActionButton, ContextualMenuItemType } from "office-ui-fabric-react";
|
|||
|
||||
import { userService } from "../../services";
|
||||
import { userActions } from "../../actions/userActions";
|
||||
import LoginDialog from "../LoginDialog//LoginDialog";
|
||||
import SignInButton from "../shared/SignInButton";
|
||||
import UserPersona from "./UserPersona";
|
||||
|
||||
class AuthControl extends Component {
|
||||
|
@ -60,8 +60,8 @@ class AuthControl extends Component {
|
|||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<LoginDialog />
|
||||
<div className="signin-button-container">
|
||||
<SignInButton />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -7,3 +7,8 @@
|
|||
.auth-control {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.signin-button-container {
|
||||
text-align: center;
|
||||
padding: 20px 16px;
|
||||
}
|
||||
|
|
|
@ -33,7 +33,11 @@ class UserPersona extends Component {
|
|||
}
|
||||
};
|
||||
|
||||
const { loggedIn, user } = this.props;
|
||||
const { loading, loggedIn, user } = this.props;
|
||||
if (loading) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return loggedIn ? (
|
||||
<Persona
|
||||
styles={personaStyles}
|
||||
|
@ -59,6 +63,7 @@ class UserPersona extends Component {
|
|||
}
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
loading: state.authentication.loading,
|
||||
loggedIn: state.authentication.loggedIn,
|
||||
user: state.authentication.user
|
||||
});
|
||||
|
|
|
@ -1,52 +0,0 @@
|
|||
import React, { Component } from "react";
|
||||
import { withRouter } from "react-router-dom";
|
||||
import { PrimaryButton } from "office-ui-fabric-react";
|
||||
|
||||
import "./LoginDialog.scss";
|
||||
|
||||
class Login extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.handleButtonClick = this.handleButtonClick.bind(this);
|
||||
}
|
||||
|
||||
handleButtonClick() {
|
||||
const currentLocation = encodeURIComponent(window.location);
|
||||
window.location = `/api/user/login?returnUrl=${currentLocation}`;
|
||||
}
|
||||
|
||||
render() {
|
||||
const buttonStyles = {
|
||||
root: {
|
||||
fontSize: "12px",
|
||||
height: "32px",
|
||||
minWidth: "130px",
|
||||
paddingRight: "10px",
|
||||
paddingLeft: "10px",
|
||||
marginBottom: "10px",
|
||||
marginTop: "10px",
|
||||
border: "1px solid",
|
||||
borderRadius: "2px"
|
||||
},
|
||||
label: {
|
||||
fontWeight: "normal"
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="login-dialog">
|
||||
<PrimaryButton
|
||||
styles={buttonStyles}
|
||||
primary={true}
|
||||
iconProps={{ iconName: "GitHub-17px" }}
|
||||
onClick={this.handleButtonClick}
|
||||
>
|
||||
Sign in with GitHub
|
||||
</PrimaryButton>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withRouter(Login);
|
|
@ -1,5 +0,0 @@
|
|||
.login-dialog {
|
||||
min-width: 200px;
|
||||
text-align: center;
|
||||
padding: 10px 16px;
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
import React, { Component } from "react";
|
||||
import { Route, Redirect } from "react-router-dom";
|
||||
import { connect } from "react-redux";
|
||||
|
||||
class PrivateRoute extends Component {
|
||||
render() {
|
||||
const { component: Component, loggedIn, ...rest } = this.props;
|
||||
|
||||
return (
|
||||
<Route
|
||||
{...rest}
|
||||
render={props =>
|
||||
loggedIn ? (
|
||||
<Component {...props} />
|
||||
) : (
|
||||
<Redirect
|
||||
to={{ pathname: "/login", state: { from: props.location } }}
|
||||
/>
|
||||
)
|
||||
}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
loggedIn: state.authentication.loggedIn
|
||||
});
|
||||
|
||||
const PrivateRouteContainer = connect(mapStateToProps)(PrivateRoute);
|
||||
|
||||
export default PrivateRouteContainer;
|
|
@ -0,0 +1,34 @@
|
|||
import React, { Component } from "react";
|
||||
import { PrimaryButton } from "office-ui-fabric-react";
|
||||
|
||||
class SignInButton extends Component {
|
||||
handleButtonClick() {
|
||||
const currentLocation = encodeURIComponent(window.location);
|
||||
window.location = `/api/user/login?returnUrl=${currentLocation}`;
|
||||
}
|
||||
|
||||
render() {
|
||||
const buttonStyles = {
|
||||
root: {
|
||||
fontSize: "12px",
|
||||
height: "32px"
|
||||
},
|
||||
label: {
|
||||
fontWeight: "normal"
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<PrimaryButton
|
||||
styles={buttonStyles}
|
||||
primary={true}
|
||||
iconProps={{ iconName: "GitHub-17px" }}
|
||||
onClick={this.handleButtonClick}
|
||||
>
|
||||
Sign in with GitHub
|
||||
</PrimaryButton>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default SignInButton;
|
|
@ -6,12 +6,25 @@ export default function authenticationReducer(
|
|||
action
|
||||
) {
|
||||
switch (action.type) {
|
||||
case userActionTypes.GETCURRENTUSER_REQUEST:
|
||||
return {
|
||||
...state,
|
||||
loading: true
|
||||
};
|
||||
case userActionTypes.GETCURRENTUSER_SUCCESS:
|
||||
return {
|
||||
...state,
|
||||
loading: false,
|
||||
loggedIn: true,
|
||||
user: action.user
|
||||
};
|
||||
case userActionTypes.GETCURRENTUSER_FAILURE:
|
||||
return {
|
||||
...state,
|
||||
loading: false,
|
||||
loggedIn: false,
|
||||
user: {}
|
||||
};
|
||||
case userActionTypes.LOGOUT:
|
||||
return {
|
||||
...state,
|
||||
|
|
|
@ -2,6 +2,7 @@ export default {
|
|||
samples: [],
|
||||
authentication: {
|
||||
loggedIn: false,
|
||||
user: {}
|
||||
user: {},
|
||||
loading: false
|
||||
}
|
||||
};
|
||||
|
|
Загрузка…
Ссылка в новой задаче