Add sign-in prompt on Contributions page (#148)

This commit is contained in:
Neha Gupta 2019-04-24 18:21:22 -07:00 коммит произвёл GitHub
Родитель 43ba412443
Коммит a8df22afe5
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
16 изменённых файлов: 173 добавлений и 106 удалений

Просмотреть файл

@ -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
}
};